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 31aedaa0e5Sjeremylt for (CeedInt i=0; i<impl->numein; i++) { 32*91703d3fSjeremylt ierr = CeedVectorDestroy(&impl->evecsin[i]); CeedChk(ierr); 33aedaa0e5Sjeremylt ierr = CeedVectorDestroy(&impl->qvecsin[i]); CeedChk(ierr); 34885ac19cSjeremylt } 35*91703d3fSjeremylt ierr = CeedFree(&impl->evecsin); CeedChk(ierr); 36aedaa0e5Sjeremylt ierr = CeedFree(&impl->qvecsin); CeedChk(ierr); 37885ac19cSjeremylt 38aedaa0e5Sjeremylt for (CeedInt i=0; i<impl->numeout; i++) { 39*91703d3fSjeremylt ierr = CeedVectorDestroy(&impl->evecsout[i]); CeedChk(ierr); 40aedaa0e5Sjeremylt ierr = CeedVectorDestroy(&impl->qvecsout[i]); CeedChk(ierr); 41aedaa0e5Sjeremylt } 42*91703d3fSjeremylt ierr = CeedFree(&impl->evecsout); CeedChk(ierr); 43aedaa0e5Sjeremylt ierr = CeedFree(&impl->qvecsout); CeedChk(ierr); 44885ac19cSjeremylt 45fe2413ffSjeremylt ierr = CeedFree(&impl); CeedChk(ierr); 4621617c04Sjeremylt return 0; 4721617c04Sjeremylt } 4821617c04Sjeremylt 49885ac19cSjeremylt /* 50885ac19cSjeremylt Setup infields or outfields 51885ac19cSjeremylt */ 52fe2413ffSjeremylt static int CeedOperatorSetupFields_Ref(CeedQFunction qf, CeedOperator op, 53*91703d3fSjeremylt bool inOrOut, 54*91703d3fSjeremylt CeedVector *fullevecs, CeedVector *evecs, 55aedaa0e5Sjeremylt CeedVector *qvecs, CeedInt starte, 56135a076eSjeremylt CeedInt numfields, CeedInt Q) { 57aedaa0e5Sjeremylt CeedInt dim, ierr, ncomp; 58aedaa0e5Sjeremylt Ceed ceed; 59aedaa0e5Sjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 60d1bcdac9Sjeremylt CeedBasis basis; 61d1bcdac9Sjeremylt CeedElemRestriction Erestrict; 62aedaa0e5Sjeremylt CeedOperatorField *opfields; 63aedaa0e5Sjeremylt CeedQFunctionField *qffields; 64fe2413ffSjeremylt if (inOrOut) { 65aedaa0e5Sjeremylt ierr = CeedOperatorGetFields(op, NULL, &opfields); 66fe2413ffSjeremylt CeedChk(ierr); 67aedaa0e5Sjeremylt ierr = CeedQFunctionGetFields(qf, NULL, &qffields); 68fe2413ffSjeremylt CeedChk(ierr); 69fe2413ffSjeremylt } else { 70aedaa0e5Sjeremylt ierr = CeedOperatorGetFields(op, &opfields, NULL); 71fe2413ffSjeremylt CeedChk(ierr); 72aedaa0e5Sjeremylt ierr = CeedQFunctionGetFields(qf, &qffields, NULL); 73fe2413ffSjeremylt CeedChk(ierr); 74fe2413ffSjeremylt } 7521617c04Sjeremylt 76885ac19cSjeremylt // Loop over fields 77885ac19cSjeremylt for (CeedInt i=0; i<numfields; i++) { 78d1bcdac9Sjeremylt CeedEvalMode emode; 79aedaa0e5Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qffields[i], &emode); CeedChk(ierr); 80135a076eSjeremylt 81135a076eSjeremylt if (emode != CEED_EVAL_WEIGHT) { 82aedaa0e5Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opfields[i], &Erestrict); 83d1bcdac9Sjeremylt CeedChk(ierr); 84d1bcdac9Sjeremylt ierr = CeedElemRestrictionCreateVector(Erestrict, NULL, 85*91703d3fSjeremylt &fullevecs[i+starte]); 86135a076eSjeremylt CeedChk(ierr); 87135a076eSjeremylt } 88135a076eSjeremylt 89885ac19cSjeremylt switch(emode) { 90885ac19cSjeremylt case CEED_EVAL_NONE: 91aedaa0e5Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qffields[i], &ncomp); 92d1bcdac9Sjeremylt CeedChk(ierr); 93aedaa0e5Sjeremylt ierr = CeedVectorCreate(ceed, Q*ncomp, &qvecs[i]); CeedChk(ierr); 94aedaa0e5Sjeremylt break; 95aedaa0e5Sjeremylt case CEED_EVAL_INTERP: 96aedaa0e5Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qffields[i], &ncomp); 97aedaa0e5Sjeremylt CeedChk(ierr); 98*91703d3fSjeremylt ierr = CeedVectorCreate(ceed, Q*ncomp, &evecs[i]); CeedChk(ierr); 99aedaa0e5Sjeremylt ierr = CeedVectorCreate(ceed, Q*ncomp, &qvecs[i]); CeedChk(ierr); 100885ac19cSjeremylt break; 101885ac19cSjeremylt case CEED_EVAL_GRAD: 102aedaa0e5Sjeremylt ierr = CeedOperatorFieldGetBasis(opfields[i], &basis); CeedChk(ierr); 103aedaa0e5Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qffields[i], &ncomp); 104d1bcdac9Sjeremylt ierr = CeedBasisGetDimension(basis, &dim); CeedChk(ierr); 105*91703d3fSjeremylt ierr = CeedVectorCreate(ceed, Q*ncomp, &evecs[i]); CeedChk(ierr); 106aedaa0e5Sjeremylt ierr = CeedVectorCreate(ceed, Q*ncomp*dim, &qvecs[i]); CeedChk(ierr); 107885ac19cSjeremylt break; 108885ac19cSjeremylt case CEED_EVAL_WEIGHT: // Only on input fields 109aedaa0e5Sjeremylt ierr = CeedOperatorFieldGetBasis(opfields[i], &basis); CeedChk(ierr); 110aedaa0e5Sjeremylt ierr = CeedVectorCreate(ceed, Q, &qvecs[i]); CeedChk(ierr); 111d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 112aedaa0e5Sjeremylt NULL, qvecs[i]); CeedChk(ierr); 113885ac19cSjeremylt break; 114885ac19cSjeremylt case CEED_EVAL_DIV: 115885ac19cSjeremylt break; // Not implimented 116885ac19cSjeremylt case CEED_EVAL_CURL: 117885ac19cSjeremylt break; // Not implimented 11821617c04Sjeremylt } 119885ac19cSjeremylt } 12021617c04Sjeremylt return 0; 12121617c04Sjeremylt } 12221617c04Sjeremylt 123885ac19cSjeremylt /* 124885ac19cSjeremylt CeedOperator needs to connect all the named fields (be they active or passive) 125885ac19cSjeremylt to the named inputs and outputs of its CeedQFunction. 126885ac19cSjeremylt */ 127885ac19cSjeremylt static int CeedOperatorSetup_Ref(CeedOperator op) { 12821617c04Sjeremylt int ierr; 1294ce2993fSjeremylt bool setupdone; 1304ce2993fSjeremylt ierr = CeedOperatorGetSetupStatus(op, &setupdone); CeedChk(ierr); 1314ce2993fSjeremylt if (setupdone) return 0; 132aedaa0e5Sjeremylt Ceed ceed; 133aedaa0e5Sjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 1344ce2993fSjeremylt CeedOperator_Ref *impl; 1354ce2993fSjeremylt ierr = CeedOperatorGetData(op, (void*)&impl); CeedChk(ierr); 1364ce2993fSjeremylt CeedQFunction qf; 1374ce2993fSjeremylt ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 1384ce2993fSjeremylt CeedInt Q, numinputfields, numoutputfields; 1394ce2993fSjeremylt ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 140a8de75f0Sjeremylt ierr = CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 141a8de75f0Sjeremylt CeedChk(ierr); 142d1bcdac9Sjeremylt CeedOperatorField *opinputfields, *opoutputfields; 143d1bcdac9Sjeremylt ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 144d1bcdac9Sjeremylt CeedChk(ierr); 145d1bcdac9Sjeremylt CeedQFunctionField *qfinputfields, *qfoutputfields; 146d1bcdac9Sjeremylt ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 147d1bcdac9Sjeremylt CeedChk(ierr); 148885ac19cSjeremylt 149885ac19cSjeremylt // Allocate 150aedaa0e5Sjeremylt ierr = CeedCalloc(numinputfields + numoutputfields, &impl->evecs); 151aedaa0e5Sjeremylt CeedChk(ierr); 152aedaa0e5Sjeremylt ierr = CeedCalloc(numinputfields + numoutputfields, &impl->edata); 153885ac19cSjeremylt CeedChk(ierr); 154885ac19cSjeremylt 155*91703d3fSjeremylt ierr = CeedCalloc(16, &impl->evecsin); CeedChk(ierr); 156*91703d3fSjeremylt ierr = CeedCalloc(16, &impl->evecsout); CeedChk(ierr); 157aedaa0e5Sjeremylt ierr = CeedCalloc(16, &impl->qvecsin); CeedChk(ierr); 158aedaa0e5Sjeremylt ierr = CeedCalloc(16, &impl->qvecsout); CeedChk(ierr); 159885ac19cSjeremylt 160aedaa0e5Sjeremylt impl->numein = numinputfields; impl->numeout = numoutputfields; 161885ac19cSjeremylt 162aedaa0e5Sjeremylt // Set up infield and outfield evecs and qvecs 163885ac19cSjeremylt // Infields 164*91703d3fSjeremylt ierr = CeedOperatorSetupFields_Ref(qf, op, 0, impl->evecs, 165*91703d3fSjeremylt impl->evecsin, impl->qvecsin, 0, 166aedaa0e5Sjeremylt numinputfields, Q); 167aedaa0e5Sjeremylt CeedChk(ierr); 168885ac19cSjeremylt 169885ac19cSjeremylt // Outfields 170*91703d3fSjeremylt ierr = CeedOperatorSetupFields_Ref(qf, op, 1, impl->evecs, 171*91703d3fSjeremylt impl->evecsout, impl->qvecsout, 172aedaa0e5Sjeremylt numinputfields, numoutputfields, Q); 173d1bcdac9Sjeremylt CeedChk(ierr); 174885ac19cSjeremylt 1754ce2993fSjeremylt ierr = CeedOperatorSetSetupDone(op); CeedChk(ierr); 176885ac19cSjeremylt 177885ac19cSjeremylt return 0; 178885ac19cSjeremylt } 179885ac19cSjeremylt 180885ac19cSjeremylt static int CeedOperatorApply_Ref(CeedOperator op, CeedVector invec, 181885ac19cSjeremylt CeedVector outvec, CeedRequest *request) { 182885ac19cSjeremylt int ierr; 1834ce2993fSjeremylt CeedOperator_Ref *impl; 1844ce2993fSjeremylt ierr = CeedOperatorGetData(op, (void*)&impl); CeedChk(ierr); 1854ce2993fSjeremylt CeedQFunction qf; 1864ce2993fSjeremylt ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 187d1bcdac9Sjeremylt CeedInt Q, numelements, elemsize, numinputfields, numoutputfields, ncomp; 1884ce2993fSjeremylt ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 1894ce2993fSjeremylt ierr = CeedOperatorGetNumElements(op, &numelements); CeedChk(ierr); 1904ce2993fSjeremylt ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 1914ce2993fSjeremylt CeedChk(ierr); 1924dccadb6Sjeremylt CeedTransposeMode lmode; 193d1bcdac9Sjeremylt CeedOperatorField *opinputfields, *opoutputfields; 194d1bcdac9Sjeremylt ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 195d1bcdac9Sjeremylt CeedChk(ierr); 196d1bcdac9Sjeremylt CeedQFunctionField *qfinputfields, *qfoutputfields; 197d1bcdac9Sjeremylt ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 198d1bcdac9Sjeremylt CeedChk(ierr); 199d1bcdac9Sjeremylt CeedEvalMode emode; 200d1bcdac9Sjeremylt CeedVector vec; 201d1bcdac9Sjeremylt CeedBasis basis; 202d1bcdac9Sjeremylt CeedElemRestriction Erestrict; 203885ac19cSjeremylt 204885ac19cSjeremylt // Setup 205885ac19cSjeremylt ierr = CeedOperatorSetup_Ref(op); CeedChk(ierr); 206885ac19cSjeremylt 207885ac19cSjeremylt // Input Evecs and Restriction 2081a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 209d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 210d1bcdac9Sjeremylt CeedChk(ierr); 211135a076eSjeremylt if (emode == CEED_EVAL_WEIGHT) { // Skip 212668048e2SJed Brown } else { 213d1bcdac9Sjeremylt // Get input vector 214d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opinputfields[i], &vec); CeedChk(ierr); 215d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 216d1bcdac9Sjeremylt vec = invec; 217668048e2SJed Brown // Restrict 218d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); 219d1bcdac9Sjeremylt CeedChk(ierr); 2204dccadb6Sjeremylt ierr = CeedOperatorFieldGetLMode(opinputfields[i], &lmode); CeedChk(ierr); 221d1bcdac9Sjeremylt ierr = CeedElemRestrictionApply(Erestrict, CEED_NOTRANSPOSE, 222d1bcdac9Sjeremylt lmode, vec, impl->evecs[i], 223668048e2SJed Brown request); CeedChk(ierr); 224668048e2SJed Brown // Get evec 225a2b73c81Sjeremylt ierr = CeedVectorGetArrayRead(impl->evecs[i], CEED_MEM_HOST, 226d1bcdac9Sjeremylt (const CeedScalar **) &impl->edata[i]); 227d1bcdac9Sjeremylt CeedChk(ierr); 228885ac19cSjeremylt } 229885ac19cSjeremylt } 230885ac19cSjeremylt 231885ac19cSjeremylt // Output Evecs 2321a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 233a2b73c81Sjeremylt ierr = CeedVectorGetArray(impl->evecs[i+impl->numein], CEED_MEM_HOST, 2341a4ead9bSjeremylt &impl->edata[i + numinputfields]); CeedChk(ierr); 235885ac19cSjeremylt } 236885ac19cSjeremylt 237885ac19cSjeremylt // Loop through elements 2384ce2993fSjeremylt for (CeedInt e=0; e<numelements; e++) { 239885ac19cSjeremylt // Input basis apply if needed 2401a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 241135a076eSjeremylt // Get elemsize, emode, ncomp 242d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); 243d1bcdac9Sjeremylt CeedChk(ierr); 244d1bcdac9Sjeremylt ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize); 245d1bcdac9Sjeremylt CeedChk(ierr); 246d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 247d1bcdac9Sjeremylt CeedChk(ierr); 248d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfinputfields[i], &ncomp); 249d1bcdac9Sjeremylt CeedChk(ierr); 250885ac19cSjeremylt // Basis action 251885ac19cSjeremylt switch(emode) { 252885ac19cSjeremylt case CEED_EVAL_NONE: 253aedaa0e5Sjeremylt ierr = CeedVectorSetArray(impl->qvecsin[i], CEED_MEM_HOST, 254aedaa0e5Sjeremylt CEED_USE_POINTER, 255aedaa0e5Sjeremylt &impl->edata[i][e*Q*ncomp]); CeedChk(ierr); 256885ac19cSjeremylt break; 257885ac19cSjeremylt case CEED_EVAL_INTERP: 258d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); CeedChk(ierr); 259*91703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsin[i], CEED_MEM_HOST, 260aedaa0e5Sjeremylt CEED_USE_POINTER, 261aedaa0e5Sjeremylt &impl->edata[i][e*elemsize*ncomp]); 262aedaa0e5Sjeremylt CeedChk(ierr); 263d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 264*91703d3fSjeremylt CEED_EVAL_INTERP, impl->evecsin[i], 265aedaa0e5Sjeremylt impl->qvecsin[i]); CeedChk(ierr); 266885ac19cSjeremylt break; 267885ac19cSjeremylt case CEED_EVAL_GRAD: 268d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); CeedChk(ierr); 269*91703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsin[i], CEED_MEM_HOST, 270aedaa0e5Sjeremylt CEED_USE_POINTER, 271aedaa0e5Sjeremylt &impl->edata[i][e*elemsize*ncomp]); 272aedaa0e5Sjeremylt CeedChk(ierr); 273d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 274*91703d3fSjeremylt CEED_EVAL_GRAD, impl->evecsin[i], 275aedaa0e5Sjeremylt impl->qvecsin[i]); CeedChk(ierr); 276885ac19cSjeremylt break; 277885ac19cSjeremylt case CEED_EVAL_WEIGHT: 278885ac19cSjeremylt break; // No action 279885ac19cSjeremylt case CEED_EVAL_DIV: 280885ac19cSjeremylt break; // Not implimented 281885ac19cSjeremylt case CEED_EVAL_CURL: 282885ac19cSjeremylt break; // Not implimented 283885ac19cSjeremylt } 284885ac19cSjeremylt } 285885ac19cSjeremylt // Output pointers 2861a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 287d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 288d1bcdac9Sjeremylt CeedChk(ierr); 289885ac19cSjeremylt if (emode == CEED_EVAL_NONE) { 290d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfoutputfields[i], &ncomp); 291d1bcdac9Sjeremylt CeedChk(ierr); 292aedaa0e5Sjeremylt ierr = CeedVectorSetArray(impl->qvecsout[i], CEED_MEM_HOST, 293aedaa0e5Sjeremylt CEED_USE_POINTER, 294aedaa0e5Sjeremylt &impl->edata[i + numinputfields][e*Q*ncomp]); 295aedaa0e5Sjeremylt CeedChk(ierr); 296885ac19cSjeremylt } 297885ac19cSjeremylt } 298885ac19cSjeremylt // Q function 299aedaa0e5Sjeremylt ierr = CeedQFunctionApply(qf, Q, impl->qvecsin, impl->qvecsout); CeedChk(ierr); 300885ac19cSjeremylt 301885ac19cSjeremylt // Output basis apply if needed 3021a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 303135a076eSjeremylt // Get elemsize, emode, ncomp 304d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 305d1bcdac9Sjeremylt CeedChk(ierr); 306d1bcdac9Sjeremylt ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize); 307d1bcdac9Sjeremylt CeedChk(ierr); 308d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 309d1bcdac9Sjeremylt CeedChk(ierr); 310d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfoutputfields[i], &ncomp); 311d1bcdac9Sjeremylt CeedChk(ierr); 312885ac19cSjeremylt // Basis action 313885ac19cSjeremylt switch(emode) { 314885ac19cSjeremylt case CEED_EVAL_NONE: 315885ac19cSjeremylt break; // No action 316885ac19cSjeremylt case CEED_EVAL_INTERP: 317d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); 318d1bcdac9Sjeremylt CeedChk(ierr); 319*91703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsout[i], CEED_MEM_HOST, 320aedaa0e5Sjeremylt CEED_USE_POINTER, 3211a4ead9bSjeremylt &impl->edata[i + numinputfields][e*elemsize*ncomp]); 322aedaa0e5Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 323aedaa0e5Sjeremylt CEED_EVAL_INTERP, impl->qvecsout[i], 324*91703d3fSjeremylt impl->evecsout[i]); CeedChk(ierr); 325885ac19cSjeremylt break; 326885ac19cSjeremylt case CEED_EVAL_GRAD: 327d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); 328d1bcdac9Sjeremylt CeedChk(ierr); 329*91703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsout[i], CEED_MEM_HOST, 330aedaa0e5Sjeremylt CEED_USE_POINTER, 331d1bcdac9Sjeremylt &impl->edata[i + numinputfields][e*elemsize*ncomp]); 332aedaa0e5Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 333aedaa0e5Sjeremylt CEED_EVAL_GRAD, impl->qvecsout[i], 334*91703d3fSjeremylt impl->evecsout[i]); CeedChk(ierr); 335885ac19cSjeremylt break; 3364ce2993fSjeremylt case CEED_EVAL_WEIGHT: { 3374ce2993fSjeremylt Ceed ceed; 3384ce2993fSjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 3394ce2993fSjeremylt return CeedError(ceed, 1, 3408d94b059Sjeremylt "CEED_EVAL_WEIGHT cannot be an output evaluation mode"); 341885ac19cSjeremylt break; // Should not occur 3424ce2993fSjeremylt } 343885ac19cSjeremylt case CEED_EVAL_DIV: 344885ac19cSjeremylt break; // Not implimented 345885ac19cSjeremylt case CEED_EVAL_CURL: 346885ac19cSjeremylt break; // Not implimented 347885ac19cSjeremylt } 348885ac19cSjeremylt } 349885ac19cSjeremylt } 350885ac19cSjeremylt 35142ecf959Sjeremylt // Zero lvecs 352d1bcdac9Sjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 353d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); 354d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 355d1bcdac9Sjeremylt vec = outvec; 356d1bcdac9Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 35742ecf959Sjeremylt } 35842ecf959Sjeremylt 359885ac19cSjeremylt // Output restriction 3601a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 361a2b73c81Sjeremylt // Restore evec 362a2b73c81Sjeremylt ierr = CeedVectorRestoreArray(impl->evecs[i+impl->numein], 363d1bcdac9Sjeremylt &impl->edata[i + numinputfields]); 364d1bcdac9Sjeremylt CeedChk(ierr); 365d1bcdac9Sjeremylt // Get output vector 366d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); 367668048e2SJed Brown // Active 368d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 369d1bcdac9Sjeremylt vec = outvec; 3707ca8db16Sjeremylt // Restrict 371d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 372d1bcdac9Sjeremylt CeedChk(ierr); 3734dccadb6Sjeremylt ierr = CeedOperatorFieldGetLMode(opoutputfields[i], &lmode); CeedChk(ierr); 374d1bcdac9Sjeremylt ierr = CeedElemRestrictionApply(Erestrict, CEED_TRANSPOSE, 375d1bcdac9Sjeremylt lmode, impl->evecs[i+impl->numein], vec, 376668048e2SJed Brown request); CeedChk(ierr); 377885ac19cSjeremylt } 378885ac19cSjeremylt 3797ca8db16Sjeremylt // Restore input arrays 3801a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 381d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 382d1bcdac9Sjeremylt CeedChk(ierr); 383135a076eSjeremylt if (emode == CEED_EVAL_WEIGHT) { // Skip 3847ca8db16Sjeremylt } else { 385a2b73c81Sjeremylt ierr = CeedVectorRestoreArrayRead(impl->evecs[i], 386d1bcdac9Sjeremylt (const CeedScalar **) &impl->edata[i]); 387d1bcdac9Sjeremylt CeedChk(ierr); 3887ca8db16Sjeremylt } 3897ca8db16Sjeremylt } 3907ca8db16Sjeremylt 39121617c04Sjeremylt return 0; 39221617c04Sjeremylt } 39321617c04Sjeremylt 39421617c04Sjeremylt int CeedOperatorCreate_Ref(CeedOperator op) { 39521617c04Sjeremylt int ierr; 396fe2413ffSjeremylt Ceed ceed; 397fe2413ffSjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 3984ce2993fSjeremylt CeedOperator_Ref *impl; 39921617c04Sjeremylt 40021617c04Sjeremylt ierr = CeedCalloc(1, &impl); CeedChk(ierr); 401fe2413ffSjeremylt ierr = CeedOperatorSetData(op, (void*)&impl); 402fe2413ffSjeremylt 403fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "Apply", 404fe2413ffSjeremylt CeedOperatorApply_Ref); CeedChk(ierr); 405fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "Destroy", 406fe2413ffSjeremylt CeedOperatorDestroy_Ref); CeedChk(ierr); 40721617c04Sjeremylt return 0; 40821617c04Sjeremylt } 409