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 "ceed-ref.h" 1821617c04Sjeremylt 1921617c04Sjeremylt static int CeedOperatorDestroy_Ref(CeedOperator op) { 2021617c04Sjeremylt int ierr; 214ce2993fSjeremylt CeedOperator_Ref *impl; 224ce2993fSjeremylt ierr = CeedOperatorGetData(op, (void *)&impl); CeedChk(ierr); 2321617c04Sjeremylt 24885ac19cSjeremylt for (CeedInt i=0; i<impl->numein+impl->numeout; i++) { 25885ac19cSjeremylt ierr = CeedVectorDestroy(&impl->evecs[i]); CeedChk(ierr); 26885ac19cSjeremylt } 27885ac19cSjeremylt ierr = CeedFree(&impl->evecs); CeedChk(ierr); 28885ac19cSjeremylt ierr = CeedFree(&impl->edata); CeedChk(ierr); 298d713cf6Sjeremylt ierr = CeedFree(&impl->inputstate); CeedChk(ierr); 30885ac19cSjeremylt 31aedaa0e5Sjeremylt for (CeedInt i=0; i<impl->numein; i++) { 3291703d3fSjeremylt ierr = CeedVectorDestroy(&impl->evecsin[i]); CeedChk(ierr); 33aedaa0e5Sjeremylt ierr = CeedVectorDestroy(&impl->qvecsin[i]); CeedChk(ierr); 34885ac19cSjeremylt } 3591703d3fSjeremylt ierr = CeedFree(&impl->evecsin); CeedChk(ierr); 36aedaa0e5Sjeremylt ierr = CeedFree(&impl->qvecsin); CeedChk(ierr); 37885ac19cSjeremylt 38aedaa0e5Sjeremylt for (CeedInt i=0; i<impl->numeout; i++) { 3991703d3fSjeremylt ierr = CeedVectorDestroy(&impl->evecsout[i]); CeedChk(ierr); 40aedaa0e5Sjeremylt ierr = CeedVectorDestroy(&impl->qvecsout[i]); CeedChk(ierr); 41aedaa0e5Sjeremylt } 4291703d3fSjeremylt 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, 5391703d3fSjeremylt bool inOrOut, 5491703d3fSjeremylt CeedVector *fullevecs, CeedVector *evecs, 55aedaa0e5Sjeremylt CeedVector *qvecs, CeedInt starte, 56135a076eSjeremylt CeedInt numfields, CeedInt Q) { 574d1cd9fcSJeremy L Thompson CeedInt dim, ierr, ncomp, P; 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, 8591703d3fSjeremylt &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); 984d1cd9fcSJeremy L Thompson ierr = CeedElemRestrictionGetElementSize(Erestrict, &P); 994d1cd9fcSJeremy L Thompson CeedChk(ierr); 1004d1cd9fcSJeremy L Thompson ierr = CeedVectorCreate(ceed, P*ncomp, &evecs[i]); CeedChk(ierr); 101aedaa0e5Sjeremylt ierr = CeedVectorCreate(ceed, Q*ncomp, &qvecs[i]); CeedChk(ierr); 102885ac19cSjeremylt break; 103885ac19cSjeremylt case CEED_EVAL_GRAD: 104aedaa0e5Sjeremylt ierr = CeedOperatorFieldGetBasis(opfields[i], &basis); CeedChk(ierr); 105aedaa0e5Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qffields[i], &ncomp); 106de686571SJeremy L Thompson CeedChk(ierr); 107d1bcdac9Sjeremylt ierr = CeedBasisGetDimension(basis, &dim); CeedChk(ierr); 1084d1cd9fcSJeremy L Thompson ierr = CeedElemRestrictionGetElementSize(Erestrict, &P); 1094d1cd9fcSJeremy L Thompson CeedChk(ierr); 1104d1cd9fcSJeremy L Thompson ierr = CeedVectorCreate(ceed, P*ncomp, &evecs[i]); CeedChk(ierr); 111aedaa0e5Sjeremylt ierr = CeedVectorCreate(ceed, Q*ncomp*dim, &qvecs[i]); CeedChk(ierr); 112885ac19cSjeremylt break; 113885ac19cSjeremylt case CEED_EVAL_WEIGHT: // Only on input fields 114aedaa0e5Sjeremylt ierr = CeedOperatorFieldGetBasis(opfields[i], &basis); CeedChk(ierr); 115aedaa0e5Sjeremylt ierr = CeedVectorCreate(ceed, Q, &qvecs[i]); CeedChk(ierr); 116d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 117aedaa0e5Sjeremylt NULL, qvecs[i]); CeedChk(ierr); 118885ac19cSjeremylt break; 119885ac19cSjeremylt case CEED_EVAL_DIV: 120885ac19cSjeremylt break; // Not implimented 121885ac19cSjeremylt case CEED_EVAL_CURL: 122885ac19cSjeremylt break; // Not implimented 12321617c04Sjeremylt } 124885ac19cSjeremylt } 12521617c04Sjeremylt return 0; 12621617c04Sjeremylt } 12721617c04Sjeremylt 128885ac19cSjeremylt /* 129885ac19cSjeremylt CeedOperator needs to connect all the named fields (be they active or passive) 130885ac19cSjeremylt to the named inputs and outputs of its CeedQFunction. 131885ac19cSjeremylt */ 132885ac19cSjeremylt static int CeedOperatorSetup_Ref(CeedOperator op) { 13321617c04Sjeremylt int ierr; 1344ce2993fSjeremylt bool setupdone; 1354ce2993fSjeremylt ierr = CeedOperatorGetSetupStatus(op, &setupdone); CeedChk(ierr); 1364ce2993fSjeremylt if (setupdone) return 0; 137aedaa0e5Sjeremylt Ceed ceed; 138aedaa0e5Sjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 1394ce2993fSjeremylt CeedOperator_Ref *impl; 1404ce2993fSjeremylt ierr = CeedOperatorGetData(op, (void *)&impl); CeedChk(ierr); 1414ce2993fSjeremylt CeedQFunction qf; 1424ce2993fSjeremylt ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 1434ce2993fSjeremylt CeedInt Q, numinputfields, numoutputfields; 1444ce2993fSjeremylt ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 145a8de75f0Sjeremylt ierr = CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 146a8de75f0Sjeremylt CeedChk(ierr); 147d1bcdac9Sjeremylt CeedOperatorField *opinputfields, *opoutputfields; 148d1bcdac9Sjeremylt ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 149d1bcdac9Sjeremylt CeedChk(ierr); 150d1bcdac9Sjeremylt CeedQFunctionField *qfinputfields, *qfoutputfields; 151d1bcdac9Sjeremylt ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 152d1bcdac9Sjeremylt CeedChk(ierr); 153885ac19cSjeremylt 154885ac19cSjeremylt // Allocate 155aedaa0e5Sjeremylt ierr = CeedCalloc(numinputfields + numoutputfields, &impl->evecs); 156aedaa0e5Sjeremylt CeedChk(ierr); 157aedaa0e5Sjeremylt ierr = CeedCalloc(numinputfields + numoutputfields, &impl->edata); 158885ac19cSjeremylt CeedChk(ierr); 159885ac19cSjeremylt 1608d713cf6Sjeremylt ierr = CeedCalloc(16, &impl->inputstate); CeedChk(ierr); 16191703d3fSjeremylt ierr = CeedCalloc(16, &impl->evecsin); CeedChk(ierr); 16291703d3fSjeremylt ierr = CeedCalloc(16, &impl->evecsout); CeedChk(ierr); 163aedaa0e5Sjeremylt ierr = CeedCalloc(16, &impl->qvecsin); CeedChk(ierr); 164aedaa0e5Sjeremylt ierr = CeedCalloc(16, &impl->qvecsout); CeedChk(ierr); 165885ac19cSjeremylt 166aedaa0e5Sjeremylt impl->numein = numinputfields; impl->numeout = numoutputfields; 167885ac19cSjeremylt 168aedaa0e5Sjeremylt // Set up infield and outfield evecs and qvecs 169885ac19cSjeremylt // Infields 17091703d3fSjeremylt ierr = CeedOperatorSetupFields_Ref(qf, op, 0, impl->evecs, 17191703d3fSjeremylt impl->evecsin, impl->qvecsin, 0, 172aedaa0e5Sjeremylt numinputfields, Q); 173aedaa0e5Sjeremylt CeedChk(ierr); 174885ac19cSjeremylt 175885ac19cSjeremylt // Outfields 17691703d3fSjeremylt ierr = CeedOperatorSetupFields_Ref(qf, op, 1, impl->evecs, 17791703d3fSjeremylt impl->evecsout, impl->qvecsout, 178aedaa0e5Sjeremylt numinputfields, numoutputfields, Q); 179d1bcdac9Sjeremylt CeedChk(ierr); 180885ac19cSjeremylt 1814ce2993fSjeremylt ierr = CeedOperatorSetSetupDone(op); CeedChk(ierr); 182885ac19cSjeremylt 183885ac19cSjeremylt return 0; 184885ac19cSjeremylt } 185885ac19cSjeremylt 186885ac19cSjeremylt static int CeedOperatorApply_Ref(CeedOperator op, CeedVector invec, 187885ac19cSjeremylt CeedVector outvec, CeedRequest *request) { 188885ac19cSjeremylt int ierr; 1894ce2993fSjeremylt CeedOperator_Ref *impl; 1904ce2993fSjeremylt ierr = CeedOperatorGetData(op, (void *)&impl); CeedChk(ierr); 1914ce2993fSjeremylt CeedQFunction qf; 1924ce2993fSjeremylt ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 193d1bcdac9Sjeremylt CeedInt Q, numelements, elemsize, numinputfields, numoutputfields, ncomp; 1944ce2993fSjeremylt ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 1954ce2993fSjeremylt ierr = CeedOperatorGetNumElements(op, &numelements); CeedChk(ierr); 1964ce2993fSjeremylt ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 1974ce2993fSjeremylt CeedChk(ierr); 1984dccadb6Sjeremylt CeedTransposeMode lmode; 199d1bcdac9Sjeremylt CeedOperatorField *opinputfields, *opoutputfields; 200d1bcdac9Sjeremylt ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 201d1bcdac9Sjeremylt CeedChk(ierr); 202d1bcdac9Sjeremylt CeedQFunctionField *qfinputfields, *qfoutputfields; 203d1bcdac9Sjeremylt ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 204d1bcdac9Sjeremylt CeedChk(ierr); 205d1bcdac9Sjeremylt CeedEvalMode emode; 206d1bcdac9Sjeremylt CeedVector vec; 207d1bcdac9Sjeremylt CeedBasis basis; 208d1bcdac9Sjeremylt CeedElemRestriction Erestrict; 2098d713cf6Sjeremylt uint64_t state; 210885ac19cSjeremylt 211885ac19cSjeremylt // Setup 212885ac19cSjeremylt ierr = CeedOperatorSetup_Ref(op); CeedChk(ierr); 213885ac19cSjeremylt 214885ac19cSjeremylt // Input Evecs and Restriction 2151a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 216d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 217d1bcdac9Sjeremylt CeedChk(ierr); 218135a076eSjeremylt if (emode == CEED_EVAL_WEIGHT) { // Skip 219668048e2SJed Brown } else { 220d1bcdac9Sjeremylt // Get input vector 221d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opinputfields[i], &vec); CeedChk(ierr); 222d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 223d1bcdac9Sjeremylt vec = invec; 224668048e2SJed Brown // Restrict 2258d713cf6Sjeremylt ierr = CeedVectorGetState(vec, &state); CeedChk(ierr); 2268d713cf6Sjeremylt // Skip restriction if input is unchanged 2278d713cf6Sjeremylt if (state != impl->inputstate[i] || vec == invec) { 228d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); 229d1bcdac9Sjeremylt CeedChk(ierr); 2304dccadb6Sjeremylt ierr = CeedOperatorFieldGetLMode(opinputfields[i], &lmode); CeedChk(ierr); 231d1bcdac9Sjeremylt ierr = CeedElemRestrictionApply(Erestrict, CEED_NOTRANSPOSE, 232d1bcdac9Sjeremylt lmode, vec, impl->evecs[i], 233668048e2SJed Brown request); CeedChk(ierr); 2348d713cf6Sjeremylt impl->inputstate[i] = state; 2358d713cf6Sjeremylt } 236668048e2SJed Brown // Get evec 237a2b73c81Sjeremylt ierr = CeedVectorGetArrayRead(impl->evecs[i], CEED_MEM_HOST, 238d1bcdac9Sjeremylt (const CeedScalar **) &impl->edata[i]); 239d1bcdac9Sjeremylt 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 254d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); 255d1bcdac9Sjeremylt CeedChk(ierr); 256d1bcdac9Sjeremylt ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize); 257d1bcdac9Sjeremylt CeedChk(ierr); 258d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 259d1bcdac9Sjeremylt CeedChk(ierr); 260d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfinputfields[i], &ncomp); 261d1bcdac9Sjeremylt CeedChk(ierr); 262885ac19cSjeremylt // Basis action 263885ac19cSjeremylt switch(emode) { 264885ac19cSjeremylt case CEED_EVAL_NONE: 265aedaa0e5Sjeremylt ierr = CeedVectorSetArray(impl->qvecsin[i], CEED_MEM_HOST, 266aedaa0e5Sjeremylt CEED_USE_POINTER, 267aedaa0e5Sjeremylt &impl->edata[i][e*Q*ncomp]); CeedChk(ierr); 268885ac19cSjeremylt break; 269885ac19cSjeremylt case CEED_EVAL_INTERP: 270d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); CeedChk(ierr); 27191703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsin[i], CEED_MEM_HOST, 272aedaa0e5Sjeremylt CEED_USE_POINTER, 273aedaa0e5Sjeremylt &impl->edata[i][e*elemsize*ncomp]); 274aedaa0e5Sjeremylt CeedChk(ierr); 275d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 27691703d3fSjeremylt CEED_EVAL_INTERP, impl->evecsin[i], 277aedaa0e5Sjeremylt impl->qvecsin[i]); CeedChk(ierr); 278885ac19cSjeremylt break; 279885ac19cSjeremylt case CEED_EVAL_GRAD: 280d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); CeedChk(ierr); 28191703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsin[i], CEED_MEM_HOST, 282aedaa0e5Sjeremylt CEED_USE_POINTER, 283aedaa0e5Sjeremylt &impl->edata[i][e*elemsize*ncomp]); 284aedaa0e5Sjeremylt CeedChk(ierr); 285d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 28691703d3fSjeremylt CEED_EVAL_GRAD, impl->evecsin[i], 287aedaa0e5Sjeremylt impl->qvecsin[i]); CeedChk(ierr); 288885ac19cSjeremylt break; 289885ac19cSjeremylt case CEED_EVAL_WEIGHT: 290885ac19cSjeremylt break; // No action 291885ac19cSjeremylt case CEED_EVAL_DIV: 292885ac19cSjeremylt break; // Not implimented 293885ac19cSjeremylt case CEED_EVAL_CURL: 294885ac19cSjeremylt break; // Not implimented 295885ac19cSjeremylt } 296885ac19cSjeremylt } 297885ac19cSjeremylt // Output pointers 2981a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 299d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 300d1bcdac9Sjeremylt CeedChk(ierr); 301885ac19cSjeremylt if (emode == CEED_EVAL_NONE) { 302d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfoutputfields[i], &ncomp); 303d1bcdac9Sjeremylt CeedChk(ierr); 304aedaa0e5Sjeremylt ierr = CeedVectorSetArray(impl->qvecsout[i], CEED_MEM_HOST, 305aedaa0e5Sjeremylt CEED_USE_POINTER, 306aedaa0e5Sjeremylt &impl->edata[i + numinputfields][e*Q*ncomp]); 307aedaa0e5Sjeremylt CeedChk(ierr); 308885ac19cSjeremylt } 309885ac19cSjeremylt } 310885ac19cSjeremylt // Q function 311aedaa0e5Sjeremylt ierr = CeedQFunctionApply(qf, Q, impl->qvecsin, impl->qvecsout); CeedChk(ierr); 312885ac19cSjeremylt 313885ac19cSjeremylt // Output basis apply if needed 3141a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 315135a076eSjeremylt // Get elemsize, emode, ncomp 316d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 317d1bcdac9Sjeremylt CeedChk(ierr); 318d1bcdac9Sjeremylt ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize); 319d1bcdac9Sjeremylt CeedChk(ierr); 320d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 321d1bcdac9Sjeremylt CeedChk(ierr); 322d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfoutputfields[i], &ncomp); 323d1bcdac9Sjeremylt CeedChk(ierr); 324885ac19cSjeremylt // Basis action 325885ac19cSjeremylt switch(emode) { 326885ac19cSjeremylt case CEED_EVAL_NONE: 327885ac19cSjeremylt break; // No action 328885ac19cSjeremylt case CEED_EVAL_INTERP: 329d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); 330d1bcdac9Sjeremylt CeedChk(ierr); 33191703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsout[i], CEED_MEM_HOST, 332aedaa0e5Sjeremylt CEED_USE_POINTER, 3331a4ead9bSjeremylt &impl->edata[i + numinputfields][e*elemsize*ncomp]); 334de686571SJeremy L Thompson CeedChk(ierr); 335aedaa0e5Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 336aedaa0e5Sjeremylt CEED_EVAL_INTERP, impl->qvecsout[i], 33791703d3fSjeremylt impl->evecsout[i]); CeedChk(ierr); 338885ac19cSjeremylt break; 339885ac19cSjeremylt case CEED_EVAL_GRAD: 340d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); 341d1bcdac9Sjeremylt CeedChk(ierr); 34291703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsout[i], CEED_MEM_HOST, 343aedaa0e5Sjeremylt CEED_USE_POINTER, 344d1bcdac9Sjeremylt &impl->edata[i + numinputfields][e*elemsize*ncomp]); 345de686571SJeremy L Thompson CeedChk(ierr); 346aedaa0e5Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 347aedaa0e5Sjeremylt CEED_EVAL_GRAD, impl->qvecsout[i], 34891703d3fSjeremylt impl->evecsout[i]); CeedChk(ierr); 349885ac19cSjeremylt break; 3504ce2993fSjeremylt case CEED_EVAL_WEIGHT: { 3514ce2993fSjeremylt Ceed ceed; 3524ce2993fSjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 3534ce2993fSjeremylt return CeedError(ceed, 1, 3548d94b059Sjeremylt "CEED_EVAL_WEIGHT cannot be an output evaluation mode"); 355885ac19cSjeremylt break; // Should not occur 3564ce2993fSjeremylt } 357885ac19cSjeremylt case CEED_EVAL_DIV: 358*8c91a0c9SJeremy L Thompson break; // Not implemented 359885ac19cSjeremylt case CEED_EVAL_CURL: 360*8c91a0c9SJeremy L Thompson break; // Not implemented 361885ac19cSjeremylt } 362885ac19cSjeremylt } 363885ac19cSjeremylt } 364885ac19cSjeremylt 36542ecf959Sjeremylt // Zero lvecs 366d1bcdac9Sjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 367d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); 36852d6035fSJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) { 36952d6035fSJeremy L Thompson if (!impl->add) { 370d1bcdac9Sjeremylt vec = outvec; 371d1bcdac9Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 37242ecf959Sjeremylt } 37352d6035fSJeremy L Thompson } else { 37452d6035fSJeremy L Thompson ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 37552d6035fSJeremy L Thompson } 37652d6035fSJeremy L Thompson } 37752d6035fSJeremy L Thompson impl->add = false; 37842ecf959Sjeremylt 379885ac19cSjeremylt // Output restriction 3801a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 381a2b73c81Sjeremylt // Restore evec 382a2b73c81Sjeremylt ierr = CeedVectorRestoreArray(impl->evecs[i+impl->numein], 383d1bcdac9Sjeremylt &impl->edata[i + numinputfields]); 384d1bcdac9Sjeremylt CeedChk(ierr); 385d1bcdac9Sjeremylt // Get output vector 386d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); 387668048e2SJed Brown // Active 388d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 389d1bcdac9Sjeremylt vec = outvec; 3907ca8db16Sjeremylt // Restrict 391d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 392d1bcdac9Sjeremylt CeedChk(ierr); 3934dccadb6Sjeremylt ierr = CeedOperatorFieldGetLMode(opoutputfields[i], &lmode); CeedChk(ierr); 394d1bcdac9Sjeremylt ierr = CeedElemRestrictionApply(Erestrict, CEED_TRANSPOSE, 395d1bcdac9Sjeremylt lmode, impl->evecs[i+impl->numein], vec, 396668048e2SJed Brown request); CeedChk(ierr); 397885ac19cSjeremylt } 398885ac19cSjeremylt 3997ca8db16Sjeremylt // Restore input arrays 4001a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 401d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 402d1bcdac9Sjeremylt CeedChk(ierr); 403135a076eSjeremylt if (emode == CEED_EVAL_WEIGHT) { // Skip 4047ca8db16Sjeremylt } else { 405a2b73c81Sjeremylt ierr = CeedVectorRestoreArrayRead(impl->evecs[i], 406d1bcdac9Sjeremylt (const CeedScalar **) &impl->edata[i]); 407d1bcdac9Sjeremylt CeedChk(ierr); 4087ca8db16Sjeremylt } 4097ca8db16Sjeremylt } 4107ca8db16Sjeremylt 41121617c04Sjeremylt return 0; 41221617c04Sjeremylt } 41321617c04Sjeremylt 41452d6035fSJeremy L Thompson static int CeedCompositeOperatorApply_Ref(CeedOperator op, CeedVector invec, 41552d6035fSJeremy L Thompson CeedVector outvec, 41652d6035fSJeremy L Thompson CeedRequest *request) { 41752d6035fSJeremy L Thompson int ierr; 41852d6035fSJeremy L Thompson CeedInt numsub; 41952d6035fSJeremy L Thompson CeedOperator_Ref *impl; 42052d6035fSJeremy L Thompson CeedOperator *suboperators; 42152d6035fSJeremy L Thompson ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 42252d6035fSJeremy L Thompson ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 42352d6035fSJeremy L Thompson 42452d6035fSJeremy L Thompson // Overwrite outvec with first output 42552d6035fSJeremy L Thompson ierr = CeedOperatorApply(suboperators[0], invec, outvec, request); 42652d6035fSJeremy L Thompson CeedChk(ierr); 42752d6035fSJeremy L Thompson // Add to outvec with subsequent outputs 42852d6035fSJeremy L Thompson for (CeedInt i=1; i<numsub; i++) { 429de686571SJeremy L Thompson ierr = CeedOperatorGetData(suboperators[i], (void *)&impl); CeedChk(ierr); 43052d6035fSJeremy L Thompson impl->add = true; 43152d6035fSJeremy L Thompson ierr = CeedOperatorApply(suboperators[i], invec, outvec, request); 43252d6035fSJeremy L Thompson CeedChk(ierr); 43352d6035fSJeremy L Thompson } 43452d6035fSJeremy L Thompson 43552d6035fSJeremy L Thompson return 0; 43652d6035fSJeremy L Thompson } 43752d6035fSJeremy L Thompson 43821617c04Sjeremylt int CeedOperatorCreate_Ref(CeedOperator op) { 43921617c04Sjeremylt int ierr; 440fe2413ffSjeremylt Ceed ceed; 441fe2413ffSjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 4424ce2993fSjeremylt CeedOperator_Ref *impl; 44321617c04Sjeremylt 44421617c04Sjeremylt ierr = CeedCalloc(1, &impl); CeedChk(ierr); 44552d6035fSJeremy L Thompson impl->add = false; 446de686571SJeremy L Thompson ierr = CeedOperatorSetData(op, (void *)&impl); CeedChk(ierr); 447fe2413ffSjeremylt 448fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "Apply", 449fe2413ffSjeremylt CeedOperatorApply_Ref); CeedChk(ierr); 450fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "Destroy", 451fe2413ffSjeremylt CeedOperatorDestroy_Ref); CeedChk(ierr); 45221617c04Sjeremylt return 0; 45321617c04Sjeremylt } 45452d6035fSJeremy L Thompson 45552d6035fSJeremy L Thompson int CeedCompositeOperatorCreate_Ref(CeedOperator op) { 45652d6035fSJeremy L Thompson int ierr; 45752d6035fSJeremy L Thompson Ceed ceed; 45852d6035fSJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 45952d6035fSJeremy L Thompson 46052d6035fSJeremy L Thompson ierr = CeedSetBackendFunction(ceed, "Operator", op, "Apply", 46152d6035fSJeremy L Thompson CeedCompositeOperatorApply_Ref); CeedChk(ierr); 46252d6035fSJeremy L Thompson return 0; 46352d6035fSJeremy L Thompson } 464