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); 30*8d713cf6Sjeremylt ierr = CeedFree(&impl->inputstate); CeedChk(ierr); 31885ac19cSjeremylt 32aedaa0e5Sjeremylt for (CeedInt i=0; i<impl->numein; i++) { 3391703d3fSjeremylt ierr = CeedVectorDestroy(&impl->evecsin[i]); CeedChk(ierr); 34aedaa0e5Sjeremylt ierr = CeedVectorDestroy(&impl->qvecsin[i]); CeedChk(ierr); 35885ac19cSjeremylt } 3691703d3fSjeremylt ierr = CeedFree(&impl->evecsin); CeedChk(ierr); 37aedaa0e5Sjeremylt ierr = CeedFree(&impl->qvecsin); CeedChk(ierr); 38885ac19cSjeremylt 39aedaa0e5Sjeremylt for (CeedInt i=0; i<impl->numeout; i++) { 4091703d3fSjeremylt ierr = CeedVectorDestroy(&impl->evecsout[i]); CeedChk(ierr); 41aedaa0e5Sjeremylt ierr = CeedVectorDestroy(&impl->qvecsout[i]); CeedChk(ierr); 42aedaa0e5Sjeremylt } 4391703d3fSjeremylt ierr = CeedFree(&impl->evecsout); CeedChk(ierr); 44aedaa0e5Sjeremylt ierr = CeedFree(&impl->qvecsout); CeedChk(ierr); 45885ac19cSjeremylt 46fe2413ffSjeremylt ierr = CeedFree(&impl); CeedChk(ierr); 4721617c04Sjeremylt return 0; 4821617c04Sjeremylt } 4921617c04Sjeremylt 50885ac19cSjeremylt /* 51885ac19cSjeremylt Setup infields or outfields 52885ac19cSjeremylt */ 53fe2413ffSjeremylt static int CeedOperatorSetupFields_Ref(CeedQFunction qf, CeedOperator op, 5491703d3fSjeremylt bool inOrOut, 5591703d3fSjeremylt CeedVector *fullevecs, CeedVector *evecs, 56aedaa0e5Sjeremylt CeedVector *qvecs, CeedInt starte, 57135a076eSjeremylt CeedInt numfields, CeedInt Q) { 58aedaa0e5Sjeremylt CeedInt dim, ierr, ncomp; 59aedaa0e5Sjeremylt Ceed ceed; 60aedaa0e5Sjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 61d1bcdac9Sjeremylt CeedBasis basis; 62d1bcdac9Sjeremylt CeedElemRestriction Erestrict; 63aedaa0e5Sjeremylt CeedOperatorField *opfields; 64aedaa0e5Sjeremylt CeedQFunctionField *qffields; 65fe2413ffSjeremylt if (inOrOut) { 66aedaa0e5Sjeremylt ierr = CeedOperatorGetFields(op, NULL, &opfields); 67fe2413ffSjeremylt CeedChk(ierr); 68aedaa0e5Sjeremylt ierr = CeedQFunctionGetFields(qf, NULL, &qffields); 69fe2413ffSjeremylt CeedChk(ierr); 70fe2413ffSjeremylt } else { 71aedaa0e5Sjeremylt ierr = CeedOperatorGetFields(op, &opfields, NULL); 72fe2413ffSjeremylt CeedChk(ierr); 73aedaa0e5Sjeremylt ierr = CeedQFunctionGetFields(qf, &qffields, NULL); 74fe2413ffSjeremylt CeedChk(ierr); 75fe2413ffSjeremylt } 7621617c04Sjeremylt 77885ac19cSjeremylt // Loop over fields 78885ac19cSjeremylt for (CeedInt i=0; i<numfields; i++) { 79d1bcdac9Sjeremylt CeedEvalMode emode; 80aedaa0e5Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qffields[i], &emode); CeedChk(ierr); 81135a076eSjeremylt 82135a076eSjeremylt if (emode != CEED_EVAL_WEIGHT) { 83aedaa0e5Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opfields[i], &Erestrict); 84d1bcdac9Sjeremylt CeedChk(ierr); 85d1bcdac9Sjeremylt ierr = CeedElemRestrictionCreateVector(Erestrict, NULL, 8691703d3fSjeremylt &fullevecs[i+starte]); 87135a076eSjeremylt CeedChk(ierr); 88135a076eSjeremylt } 89135a076eSjeremylt 90885ac19cSjeremylt switch(emode) { 91885ac19cSjeremylt case CEED_EVAL_NONE: 92aedaa0e5Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qffields[i], &ncomp); 93d1bcdac9Sjeremylt CeedChk(ierr); 94aedaa0e5Sjeremylt ierr = CeedVectorCreate(ceed, Q*ncomp, &qvecs[i]); CeedChk(ierr); 95aedaa0e5Sjeremylt break; 96aedaa0e5Sjeremylt case CEED_EVAL_INTERP: 97aedaa0e5Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qffields[i], &ncomp); 98aedaa0e5Sjeremylt CeedChk(ierr); 9991703d3fSjeremylt ierr = CeedVectorCreate(ceed, Q*ncomp, &evecs[i]); CeedChk(ierr); 100aedaa0e5Sjeremylt ierr = CeedVectorCreate(ceed, Q*ncomp, &qvecs[i]); CeedChk(ierr); 101885ac19cSjeremylt break; 102885ac19cSjeremylt case CEED_EVAL_GRAD: 103aedaa0e5Sjeremylt ierr = CeedOperatorFieldGetBasis(opfields[i], &basis); CeedChk(ierr); 104aedaa0e5Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qffields[i], &ncomp); 105d1bcdac9Sjeremylt ierr = CeedBasisGetDimension(basis, &dim); CeedChk(ierr); 10691703d3fSjeremylt ierr = CeedVectorCreate(ceed, Q*ncomp, &evecs[i]); CeedChk(ierr); 107aedaa0e5Sjeremylt ierr = CeedVectorCreate(ceed, Q*ncomp*dim, &qvecs[i]); CeedChk(ierr); 108885ac19cSjeremylt break; 109885ac19cSjeremylt case CEED_EVAL_WEIGHT: // Only on input fields 110aedaa0e5Sjeremylt ierr = CeedOperatorFieldGetBasis(opfields[i], &basis); CeedChk(ierr); 111aedaa0e5Sjeremylt ierr = CeedVectorCreate(ceed, Q, &qvecs[i]); CeedChk(ierr); 112d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 113aedaa0e5Sjeremylt NULL, qvecs[i]); CeedChk(ierr); 114885ac19cSjeremylt break; 115885ac19cSjeremylt case CEED_EVAL_DIV: 116885ac19cSjeremylt break; // Not implimented 117885ac19cSjeremylt case CEED_EVAL_CURL: 118885ac19cSjeremylt break; // Not implimented 11921617c04Sjeremylt } 120885ac19cSjeremylt } 12121617c04Sjeremylt return 0; 12221617c04Sjeremylt } 12321617c04Sjeremylt 124885ac19cSjeremylt /* 125885ac19cSjeremylt CeedOperator needs to connect all the named fields (be they active or passive) 126885ac19cSjeremylt to the named inputs and outputs of its CeedQFunction. 127885ac19cSjeremylt */ 128885ac19cSjeremylt static int CeedOperatorSetup_Ref(CeedOperator op) { 12921617c04Sjeremylt int ierr; 1304ce2993fSjeremylt bool setupdone; 1314ce2993fSjeremylt ierr = CeedOperatorGetSetupStatus(op, &setupdone); CeedChk(ierr); 1324ce2993fSjeremylt if (setupdone) return 0; 133aedaa0e5Sjeremylt Ceed ceed; 134aedaa0e5Sjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 1354ce2993fSjeremylt CeedOperator_Ref *impl; 1364ce2993fSjeremylt ierr = CeedOperatorGetData(op, (void*)&impl); CeedChk(ierr); 1374ce2993fSjeremylt CeedQFunction qf; 1384ce2993fSjeremylt ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 1394ce2993fSjeremylt CeedInt Q, numinputfields, numoutputfields; 1404ce2993fSjeremylt ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 141a8de75f0Sjeremylt ierr = CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 142a8de75f0Sjeremylt CeedChk(ierr); 143d1bcdac9Sjeremylt CeedOperatorField *opinputfields, *opoutputfields; 144d1bcdac9Sjeremylt ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 145d1bcdac9Sjeremylt CeedChk(ierr); 146d1bcdac9Sjeremylt CeedQFunctionField *qfinputfields, *qfoutputfields; 147d1bcdac9Sjeremylt ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 148d1bcdac9Sjeremylt CeedChk(ierr); 149885ac19cSjeremylt 150885ac19cSjeremylt // Allocate 151aedaa0e5Sjeremylt ierr = CeedCalloc(numinputfields + numoutputfields, &impl->evecs); 152aedaa0e5Sjeremylt CeedChk(ierr); 153aedaa0e5Sjeremylt ierr = CeedCalloc(numinputfields + numoutputfields, &impl->edata); 154885ac19cSjeremylt CeedChk(ierr); 155885ac19cSjeremylt 156*8d713cf6Sjeremylt ierr = CeedCalloc(16, &impl->inputstate); CeedChk(ierr); 15791703d3fSjeremylt ierr = CeedCalloc(16, &impl->evecsin); CeedChk(ierr); 15891703d3fSjeremylt ierr = CeedCalloc(16, &impl->evecsout); CeedChk(ierr); 159aedaa0e5Sjeremylt ierr = CeedCalloc(16, &impl->qvecsin); CeedChk(ierr); 160aedaa0e5Sjeremylt ierr = CeedCalloc(16, &impl->qvecsout); CeedChk(ierr); 161885ac19cSjeremylt 162aedaa0e5Sjeremylt impl->numein = numinputfields; impl->numeout = numoutputfields; 163885ac19cSjeremylt 164aedaa0e5Sjeremylt // Set up infield and outfield evecs and qvecs 165885ac19cSjeremylt // Infields 16691703d3fSjeremylt ierr = CeedOperatorSetupFields_Ref(qf, op, 0, impl->evecs, 16791703d3fSjeremylt impl->evecsin, impl->qvecsin, 0, 168aedaa0e5Sjeremylt numinputfields, Q); 169aedaa0e5Sjeremylt CeedChk(ierr); 170885ac19cSjeremylt 171885ac19cSjeremylt // Outfields 17291703d3fSjeremylt ierr = CeedOperatorSetupFields_Ref(qf, op, 1, impl->evecs, 17391703d3fSjeremylt impl->evecsout, impl->qvecsout, 174aedaa0e5Sjeremylt numinputfields, numoutputfields, Q); 175d1bcdac9Sjeremylt CeedChk(ierr); 176885ac19cSjeremylt 1774ce2993fSjeremylt ierr = CeedOperatorSetSetupDone(op); CeedChk(ierr); 178885ac19cSjeremylt 179885ac19cSjeremylt return 0; 180885ac19cSjeremylt } 181885ac19cSjeremylt 182885ac19cSjeremylt static int CeedOperatorApply_Ref(CeedOperator op, CeedVector invec, 183885ac19cSjeremylt CeedVector outvec, CeedRequest *request) { 184885ac19cSjeremylt int ierr; 1854ce2993fSjeremylt CeedOperator_Ref *impl; 1864ce2993fSjeremylt ierr = CeedOperatorGetData(op, (void*)&impl); CeedChk(ierr); 1874ce2993fSjeremylt CeedQFunction qf; 1884ce2993fSjeremylt ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 189d1bcdac9Sjeremylt CeedInt Q, numelements, elemsize, numinputfields, numoutputfields, ncomp; 1904ce2993fSjeremylt ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 1914ce2993fSjeremylt ierr = CeedOperatorGetNumElements(op, &numelements); CeedChk(ierr); 1924ce2993fSjeremylt ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 1934ce2993fSjeremylt CeedChk(ierr); 1944dccadb6Sjeremylt CeedTransposeMode lmode; 195d1bcdac9Sjeremylt CeedOperatorField *opinputfields, *opoutputfields; 196d1bcdac9Sjeremylt ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 197d1bcdac9Sjeremylt CeedChk(ierr); 198d1bcdac9Sjeremylt CeedQFunctionField *qfinputfields, *qfoutputfields; 199d1bcdac9Sjeremylt ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 200d1bcdac9Sjeremylt CeedChk(ierr); 201d1bcdac9Sjeremylt CeedEvalMode emode; 202d1bcdac9Sjeremylt CeedVector vec; 203d1bcdac9Sjeremylt CeedBasis basis; 204d1bcdac9Sjeremylt CeedElemRestriction Erestrict; 205*8d713cf6Sjeremylt uint64_t state; 206885ac19cSjeremylt 207885ac19cSjeremylt // Setup 208885ac19cSjeremylt ierr = CeedOperatorSetup_Ref(op); CeedChk(ierr); 209885ac19cSjeremylt 210885ac19cSjeremylt // Input Evecs and Restriction 2111a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 212d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 213d1bcdac9Sjeremylt CeedChk(ierr); 214135a076eSjeremylt if (emode == CEED_EVAL_WEIGHT) { // Skip 215668048e2SJed Brown } else { 216d1bcdac9Sjeremylt // Get input vector 217d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opinputfields[i], &vec); CeedChk(ierr); 218d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 219d1bcdac9Sjeremylt vec = invec; 220668048e2SJed Brown // Restrict 221*8d713cf6Sjeremylt ierr = CeedVectorGetState(vec, &state); CeedChk(ierr); 222*8d713cf6Sjeremylt // Skip restriction if input is unchanged 223*8d713cf6Sjeremylt if (state != impl->inputstate[i] || vec == invec) { 224d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); 225d1bcdac9Sjeremylt CeedChk(ierr); 2264dccadb6Sjeremylt ierr = CeedOperatorFieldGetLMode(opinputfields[i], &lmode); CeedChk(ierr); 227d1bcdac9Sjeremylt ierr = CeedElemRestrictionApply(Erestrict, CEED_NOTRANSPOSE, 228d1bcdac9Sjeremylt lmode, vec, impl->evecs[i], 229668048e2SJed Brown request); CeedChk(ierr); 230*8d713cf6Sjeremylt impl->inputstate[i] = state; 231*8d713cf6Sjeremylt } 232668048e2SJed Brown // Get evec 233a2b73c81Sjeremylt ierr = CeedVectorGetArrayRead(impl->evecs[i], CEED_MEM_HOST, 234d1bcdac9Sjeremylt (const CeedScalar **) &impl->edata[i]); 235d1bcdac9Sjeremylt CeedChk(ierr); 236885ac19cSjeremylt } 237885ac19cSjeremylt } 238885ac19cSjeremylt 239885ac19cSjeremylt // Output Evecs 2401a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 241a2b73c81Sjeremylt ierr = CeedVectorGetArray(impl->evecs[i+impl->numein], CEED_MEM_HOST, 2421a4ead9bSjeremylt &impl->edata[i + numinputfields]); CeedChk(ierr); 243885ac19cSjeremylt } 244885ac19cSjeremylt 245885ac19cSjeremylt // Loop through elements 2464ce2993fSjeremylt for (CeedInt e=0; e<numelements; e++) { 247885ac19cSjeremylt // Input basis apply if needed 2481a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 249135a076eSjeremylt // Get elemsize, emode, ncomp 250d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); 251d1bcdac9Sjeremylt CeedChk(ierr); 252d1bcdac9Sjeremylt ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize); 253d1bcdac9Sjeremylt CeedChk(ierr); 254d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 255d1bcdac9Sjeremylt CeedChk(ierr); 256d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfinputfields[i], &ncomp); 257d1bcdac9Sjeremylt CeedChk(ierr); 258885ac19cSjeremylt // Basis action 259885ac19cSjeremylt switch(emode) { 260885ac19cSjeremylt case CEED_EVAL_NONE: 261aedaa0e5Sjeremylt ierr = CeedVectorSetArray(impl->qvecsin[i], CEED_MEM_HOST, 262aedaa0e5Sjeremylt CEED_USE_POINTER, 263aedaa0e5Sjeremylt &impl->edata[i][e*Q*ncomp]); CeedChk(ierr); 264885ac19cSjeremylt break; 265885ac19cSjeremylt case CEED_EVAL_INTERP: 266d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); CeedChk(ierr); 26791703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsin[i], CEED_MEM_HOST, 268aedaa0e5Sjeremylt CEED_USE_POINTER, 269aedaa0e5Sjeremylt &impl->edata[i][e*elemsize*ncomp]); 270aedaa0e5Sjeremylt CeedChk(ierr); 271d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 27291703d3fSjeremylt CEED_EVAL_INTERP, impl->evecsin[i], 273aedaa0e5Sjeremylt impl->qvecsin[i]); CeedChk(ierr); 274885ac19cSjeremylt break; 275885ac19cSjeremylt case CEED_EVAL_GRAD: 276d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); CeedChk(ierr); 27791703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsin[i], CEED_MEM_HOST, 278aedaa0e5Sjeremylt CEED_USE_POINTER, 279aedaa0e5Sjeremylt &impl->edata[i][e*elemsize*ncomp]); 280aedaa0e5Sjeremylt CeedChk(ierr); 281d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 28291703d3fSjeremylt CEED_EVAL_GRAD, impl->evecsin[i], 283aedaa0e5Sjeremylt impl->qvecsin[i]); CeedChk(ierr); 284885ac19cSjeremylt break; 285885ac19cSjeremylt case CEED_EVAL_WEIGHT: 286885ac19cSjeremylt break; // No action 287885ac19cSjeremylt case CEED_EVAL_DIV: 288885ac19cSjeremylt break; // Not implimented 289885ac19cSjeremylt case CEED_EVAL_CURL: 290885ac19cSjeremylt break; // Not implimented 291885ac19cSjeremylt } 292885ac19cSjeremylt } 293885ac19cSjeremylt // Output pointers 2941a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 295d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 296d1bcdac9Sjeremylt CeedChk(ierr); 297885ac19cSjeremylt if (emode == CEED_EVAL_NONE) { 298d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfoutputfields[i], &ncomp); 299d1bcdac9Sjeremylt CeedChk(ierr); 300aedaa0e5Sjeremylt ierr = CeedVectorSetArray(impl->qvecsout[i], CEED_MEM_HOST, 301aedaa0e5Sjeremylt CEED_USE_POINTER, 302aedaa0e5Sjeremylt &impl->edata[i + numinputfields][e*Q*ncomp]); 303aedaa0e5Sjeremylt CeedChk(ierr); 304885ac19cSjeremylt } 305885ac19cSjeremylt } 306885ac19cSjeremylt // Q function 307aedaa0e5Sjeremylt ierr = CeedQFunctionApply(qf, Q, impl->qvecsin, impl->qvecsout); CeedChk(ierr); 308885ac19cSjeremylt 309885ac19cSjeremylt // Output basis apply if needed 3101a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 311135a076eSjeremylt // Get elemsize, emode, ncomp 312d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 313d1bcdac9Sjeremylt CeedChk(ierr); 314d1bcdac9Sjeremylt ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize); 315d1bcdac9Sjeremylt CeedChk(ierr); 316d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 317d1bcdac9Sjeremylt CeedChk(ierr); 318d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfoutputfields[i], &ncomp); 319d1bcdac9Sjeremylt CeedChk(ierr); 320885ac19cSjeremylt // Basis action 321885ac19cSjeremylt switch(emode) { 322885ac19cSjeremylt case CEED_EVAL_NONE: 323885ac19cSjeremylt break; // No action 324885ac19cSjeremylt case CEED_EVAL_INTERP: 325d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); 326d1bcdac9Sjeremylt CeedChk(ierr); 32791703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsout[i], CEED_MEM_HOST, 328aedaa0e5Sjeremylt CEED_USE_POINTER, 3291a4ead9bSjeremylt &impl->edata[i + numinputfields][e*elemsize*ncomp]); 330aedaa0e5Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 331aedaa0e5Sjeremylt CEED_EVAL_INTERP, impl->qvecsout[i], 33291703d3fSjeremylt impl->evecsout[i]); CeedChk(ierr); 333885ac19cSjeremylt break; 334885ac19cSjeremylt case CEED_EVAL_GRAD: 335d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); 336d1bcdac9Sjeremylt CeedChk(ierr); 33791703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsout[i], CEED_MEM_HOST, 338aedaa0e5Sjeremylt CEED_USE_POINTER, 339d1bcdac9Sjeremylt &impl->edata[i + numinputfields][e*elemsize*ncomp]); 340aedaa0e5Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 341aedaa0e5Sjeremylt CEED_EVAL_GRAD, impl->qvecsout[i], 34291703d3fSjeremylt impl->evecsout[i]); CeedChk(ierr); 343885ac19cSjeremylt break; 3444ce2993fSjeremylt case CEED_EVAL_WEIGHT: { 3454ce2993fSjeremylt Ceed ceed; 3464ce2993fSjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 3474ce2993fSjeremylt return CeedError(ceed, 1, 3488d94b059Sjeremylt "CEED_EVAL_WEIGHT cannot be an output evaluation mode"); 349885ac19cSjeremylt break; // Should not occur 3504ce2993fSjeremylt } 351885ac19cSjeremylt case CEED_EVAL_DIV: 352885ac19cSjeremylt break; // Not implimented 353885ac19cSjeremylt case CEED_EVAL_CURL: 354885ac19cSjeremylt break; // Not implimented 355885ac19cSjeremylt } 356885ac19cSjeremylt } 357885ac19cSjeremylt } 358885ac19cSjeremylt 35942ecf959Sjeremylt // Zero lvecs 360d1bcdac9Sjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 361d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); 362d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 363d1bcdac9Sjeremylt vec = outvec; 364d1bcdac9Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 36542ecf959Sjeremylt } 36642ecf959Sjeremylt 367885ac19cSjeremylt // Output restriction 3681a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 369a2b73c81Sjeremylt // Restore evec 370a2b73c81Sjeremylt ierr = CeedVectorRestoreArray(impl->evecs[i+impl->numein], 371d1bcdac9Sjeremylt &impl->edata[i + numinputfields]); 372d1bcdac9Sjeremylt CeedChk(ierr); 373d1bcdac9Sjeremylt // Get output vector 374d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); 375668048e2SJed Brown // Active 376d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 377d1bcdac9Sjeremylt vec = outvec; 3787ca8db16Sjeremylt // Restrict 379d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 380d1bcdac9Sjeremylt CeedChk(ierr); 3814dccadb6Sjeremylt ierr = CeedOperatorFieldGetLMode(opoutputfields[i], &lmode); CeedChk(ierr); 382d1bcdac9Sjeremylt ierr = CeedElemRestrictionApply(Erestrict, CEED_TRANSPOSE, 383d1bcdac9Sjeremylt lmode, impl->evecs[i+impl->numein], vec, 384668048e2SJed Brown request); CeedChk(ierr); 385885ac19cSjeremylt } 386885ac19cSjeremylt 3877ca8db16Sjeremylt // Restore input arrays 3881a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 389d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 390d1bcdac9Sjeremylt CeedChk(ierr); 391135a076eSjeremylt if (emode == CEED_EVAL_WEIGHT) { // Skip 3927ca8db16Sjeremylt } else { 393a2b73c81Sjeremylt ierr = CeedVectorRestoreArrayRead(impl->evecs[i], 394d1bcdac9Sjeremylt (const CeedScalar **) &impl->edata[i]); 395d1bcdac9Sjeremylt CeedChk(ierr); 3967ca8db16Sjeremylt } 3977ca8db16Sjeremylt } 3987ca8db16Sjeremylt 39921617c04Sjeremylt return 0; 40021617c04Sjeremylt } 40121617c04Sjeremylt 40221617c04Sjeremylt int CeedOperatorCreate_Ref(CeedOperator op) { 40321617c04Sjeremylt int ierr; 404fe2413ffSjeremylt Ceed ceed; 405fe2413ffSjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 4064ce2993fSjeremylt CeedOperator_Ref *impl; 40721617c04Sjeremylt 40821617c04Sjeremylt ierr = CeedCalloc(1, &impl); CeedChk(ierr); 409fe2413ffSjeremylt ierr = CeedOperatorSetData(op, (void*)&impl); 410fe2413ffSjeremylt 411fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "Apply", 412fe2413ffSjeremylt CeedOperatorApply_Ref); CeedChk(ierr); 413fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "Destroy", 414fe2413ffSjeremylt CeedOperatorDestroy_Ref); CeedChk(ierr); 41521617c04Sjeremylt return 0; 41621617c04Sjeremylt } 417