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) { 574d537eeaSYohann CeedInt dim, ierr, size, 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: 914d537eeaSYohann ierr = CeedQFunctionFieldGetSize(qffields[i], &size); CeedChk(ierr); 924d537eeaSYohann ierr = CeedVectorCreate(ceed, Q*size, &qvecs[i]); CeedChk(ierr); 93aedaa0e5Sjeremylt break; 94aedaa0e5Sjeremylt case CEED_EVAL_INTERP: 954d537eeaSYohann ierr = CeedQFunctionFieldGetSize(qffields[i], &size); CeedChk(ierr); 964d1cd9fcSJeremy L Thompson ierr = CeedElemRestrictionGetElementSize(Erestrict, &P); 974d1cd9fcSJeremy L Thompson CeedChk(ierr); 984d537eeaSYohann ierr = CeedVectorCreate(ceed, P*size, &evecs[i]); CeedChk(ierr); 994d537eeaSYohann ierr = CeedVectorCreate(ceed, Q*size, &qvecs[i]); CeedChk(ierr); 100885ac19cSjeremylt break; 101885ac19cSjeremylt case CEED_EVAL_GRAD: 102aedaa0e5Sjeremylt ierr = CeedOperatorFieldGetBasis(opfields[i], &basis); CeedChk(ierr); 1034d537eeaSYohann ierr = CeedQFunctionFieldGetSize(qffields[i], &size); CeedChk(ierr); 104d1bcdac9Sjeremylt ierr = CeedBasisGetDimension(basis, &dim); CeedChk(ierr); 1054d1cd9fcSJeremy L Thompson ierr = CeedElemRestrictionGetElementSize(Erestrict, &P); 1064d1cd9fcSJeremy L Thompson CeedChk(ierr); 1074d537eeaSYohann ierr = CeedVectorCreate(ceed, P*size/dim, &evecs[i]); CeedChk(ierr); 1084d537eeaSYohann ierr = CeedVectorCreate(ceed, Q*size, &qvecs[i]); CeedChk(ierr); 109885ac19cSjeremylt break; 110885ac19cSjeremylt case CEED_EVAL_WEIGHT: // Only on input fields 111aedaa0e5Sjeremylt ierr = CeedOperatorFieldGetBasis(opfields[i], &basis); CeedChk(ierr); 112aedaa0e5Sjeremylt ierr = CeedVectorCreate(ceed, Q, &qvecs[i]); CeedChk(ierr); 113d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 114aedaa0e5Sjeremylt NULL, qvecs[i]); CeedChk(ierr); 115885ac19cSjeremylt break; 116885ac19cSjeremylt case CEED_EVAL_DIV: 1174d537eeaSYohann break; // Not implemented 118885ac19cSjeremylt case CEED_EVAL_CURL: 1194d537eeaSYohann break; // Not implemented 12021617c04Sjeremylt } 121885ac19cSjeremylt } 12221617c04Sjeremylt return 0; 12321617c04Sjeremylt } 12421617c04Sjeremylt 125885ac19cSjeremylt /* 126885ac19cSjeremylt CeedOperator needs to connect all the named fields (be they active or passive) 127885ac19cSjeremylt to the named inputs and outputs of its CeedQFunction. 128885ac19cSjeremylt */ 129885ac19cSjeremylt static int CeedOperatorSetup_Ref(CeedOperator op) { 13021617c04Sjeremylt int ierr; 1314ce2993fSjeremylt bool setupdone; 1324ce2993fSjeremylt ierr = CeedOperatorGetSetupStatus(op, &setupdone); CeedChk(ierr); 1334ce2993fSjeremylt if (setupdone) return 0; 134aedaa0e5Sjeremylt Ceed ceed; 135aedaa0e5Sjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 1364ce2993fSjeremylt CeedOperator_Ref *impl; 1374ce2993fSjeremylt ierr = CeedOperatorGetData(op, (void *)&impl); CeedChk(ierr); 1384ce2993fSjeremylt CeedQFunction qf; 1394ce2993fSjeremylt ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 1404ce2993fSjeremylt CeedInt Q, numinputfields, numoutputfields; 1414ce2993fSjeremylt ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 142a8de75f0Sjeremylt ierr = CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 143a8de75f0Sjeremylt CeedChk(ierr); 144d1bcdac9Sjeremylt CeedOperatorField *opinputfields, *opoutputfields; 145d1bcdac9Sjeremylt ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 146d1bcdac9Sjeremylt CeedChk(ierr); 147d1bcdac9Sjeremylt CeedQFunctionField *qfinputfields, *qfoutputfields; 148d1bcdac9Sjeremylt ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 149d1bcdac9Sjeremylt CeedChk(ierr); 150885ac19cSjeremylt 151885ac19cSjeremylt // Allocate 152aedaa0e5Sjeremylt ierr = CeedCalloc(numinputfields + numoutputfields, &impl->evecs); 153aedaa0e5Sjeremylt CeedChk(ierr); 154aedaa0e5Sjeremylt ierr = CeedCalloc(numinputfields + numoutputfields, &impl->edata); 155885ac19cSjeremylt CeedChk(ierr); 156885ac19cSjeremylt 1578d713cf6Sjeremylt ierr = CeedCalloc(16, &impl->inputstate); CeedChk(ierr); 15891703d3fSjeremylt ierr = CeedCalloc(16, &impl->evecsin); CeedChk(ierr); 15991703d3fSjeremylt ierr = CeedCalloc(16, &impl->evecsout); CeedChk(ierr); 160aedaa0e5Sjeremylt ierr = CeedCalloc(16, &impl->qvecsin); CeedChk(ierr); 161aedaa0e5Sjeremylt ierr = CeedCalloc(16, &impl->qvecsout); CeedChk(ierr); 162885ac19cSjeremylt 163aedaa0e5Sjeremylt impl->numein = numinputfields; impl->numeout = numoutputfields; 164885ac19cSjeremylt 165aedaa0e5Sjeremylt // Set up infield and outfield evecs and qvecs 166885ac19cSjeremylt // Infields 16791703d3fSjeremylt ierr = CeedOperatorSetupFields_Ref(qf, op, 0, impl->evecs, 16891703d3fSjeremylt impl->evecsin, impl->qvecsin, 0, 169aedaa0e5Sjeremylt numinputfields, Q); 170aedaa0e5Sjeremylt CeedChk(ierr); 171885ac19cSjeremylt 172885ac19cSjeremylt // Outfields 17391703d3fSjeremylt ierr = CeedOperatorSetupFields_Ref(qf, op, 1, impl->evecs, 17491703d3fSjeremylt impl->evecsout, impl->qvecsout, 175aedaa0e5Sjeremylt numinputfields, numoutputfields, Q); 176d1bcdac9Sjeremylt CeedChk(ierr); 177885ac19cSjeremylt 1784ce2993fSjeremylt ierr = CeedOperatorSetSetupDone(op); CeedChk(ierr); 179885ac19cSjeremylt 180885ac19cSjeremylt return 0; 181885ac19cSjeremylt } 182885ac19cSjeremylt 183885ac19cSjeremylt static int CeedOperatorApply_Ref(CeedOperator op, CeedVector invec, 184885ac19cSjeremylt CeedVector outvec, CeedRequest *request) { 185885ac19cSjeremylt int ierr; 1864ce2993fSjeremylt CeedOperator_Ref *impl; 1874ce2993fSjeremylt ierr = CeedOperatorGetData(op, (void *)&impl); CeedChk(ierr); 1884ce2993fSjeremylt CeedQFunction qf; 1894ce2993fSjeremylt ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 1904d537eeaSYohann CeedInt Q, numelements, elemsize, numinputfields, numoutputfields, size, dim; 1914ce2993fSjeremylt ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 1924ce2993fSjeremylt ierr = CeedOperatorGetNumElements(op, &numelements); CeedChk(ierr); 1934ce2993fSjeremylt ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 1944ce2993fSjeremylt CeedChk(ierr); 1954dccadb6Sjeremylt CeedTransposeMode lmode; 196d1bcdac9Sjeremylt CeedOperatorField *opinputfields, *opoutputfields; 197d1bcdac9Sjeremylt ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 198d1bcdac9Sjeremylt CeedChk(ierr); 199d1bcdac9Sjeremylt CeedQFunctionField *qfinputfields, *qfoutputfields; 200d1bcdac9Sjeremylt ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 201d1bcdac9Sjeremylt CeedChk(ierr); 202d1bcdac9Sjeremylt CeedEvalMode emode; 203d1bcdac9Sjeremylt CeedVector vec; 204d1bcdac9Sjeremylt CeedBasis basis; 205d1bcdac9Sjeremylt CeedElemRestriction Erestrict; 2068d713cf6Sjeremylt uint64_t state; 207885ac19cSjeremylt 208885ac19cSjeremylt // Setup 209885ac19cSjeremylt ierr = CeedOperatorSetup_Ref(op); CeedChk(ierr); 210885ac19cSjeremylt 211885ac19cSjeremylt // Input Evecs and Restriction 2121a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 213d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 214d1bcdac9Sjeremylt CeedChk(ierr); 215135a076eSjeremylt if (emode == CEED_EVAL_WEIGHT) { // Skip 216668048e2SJed Brown } else { 217d1bcdac9Sjeremylt // Get input vector 218d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opinputfields[i], &vec); CeedChk(ierr); 219d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 220d1bcdac9Sjeremylt vec = invec; 221668048e2SJed Brown // Restrict 2228d713cf6Sjeremylt ierr = CeedVectorGetState(vec, &state); CeedChk(ierr); 2238d713cf6Sjeremylt // Skip restriction if input is unchanged 2248d713cf6Sjeremylt if (state != impl->inputstate[i] || vec == invec) { 225d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); 226d1bcdac9Sjeremylt CeedChk(ierr); 2274dccadb6Sjeremylt ierr = CeedOperatorFieldGetLMode(opinputfields[i], &lmode); CeedChk(ierr); 228d1bcdac9Sjeremylt ierr = CeedElemRestrictionApply(Erestrict, CEED_NOTRANSPOSE, 229d1bcdac9Sjeremylt lmode, vec, impl->evecs[i], 230668048e2SJed Brown request); CeedChk(ierr); 2318d713cf6Sjeremylt impl->inputstate[i] = state; 2328d713cf6Sjeremylt } 233668048e2SJed Brown // Get evec 234a2b73c81Sjeremylt ierr = CeedVectorGetArrayRead(impl->evecs[i], CEED_MEM_HOST, 235d1bcdac9Sjeremylt (const CeedScalar **) &impl->edata[i]); 236d1bcdac9Sjeremylt CeedChk(ierr); 237885ac19cSjeremylt } 238885ac19cSjeremylt } 239885ac19cSjeremylt 240885ac19cSjeremylt // Output Evecs 2411a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 242a2b73c81Sjeremylt ierr = CeedVectorGetArray(impl->evecs[i+impl->numein], CEED_MEM_HOST, 2431a4ead9bSjeremylt &impl->edata[i + numinputfields]); CeedChk(ierr); 244885ac19cSjeremylt } 245885ac19cSjeremylt 246885ac19cSjeremylt // Loop through elements 2474ce2993fSjeremylt for (CeedInt e=0; e<numelements; e++) { 248885ac19cSjeremylt // Input basis apply if needed 2491a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 2504d537eeaSYohann // Get elemsize, emode, size 251d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); 252d1bcdac9Sjeremylt CeedChk(ierr); 253d1bcdac9Sjeremylt ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize); 254d1bcdac9Sjeremylt CeedChk(ierr); 255d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 256d1bcdac9Sjeremylt CeedChk(ierr); 2574d537eeaSYohann ierr = CeedQFunctionFieldGetSize(qfinputfields[i], &size); 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, 2634d537eeaSYohann &impl->edata[i][e*Q*size]); 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, 2694d537eeaSYohann &impl->edata[i][e*elemsize*size]); 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); 2774d537eeaSYohann ierr = CeedBasisGetDimension(basis, &dim); CeedChk(ierr); 27891703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsin[i], CEED_MEM_HOST, 279aedaa0e5Sjeremylt CEED_USE_POINTER, 2804d537eeaSYohann &impl->edata[i][e*elemsize*size/dim]); 281aedaa0e5Sjeremylt CeedChk(ierr); 282d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 28391703d3fSjeremylt CEED_EVAL_GRAD, impl->evecsin[i], 284aedaa0e5Sjeremylt impl->qvecsin[i]); CeedChk(ierr); 285885ac19cSjeremylt break; 286885ac19cSjeremylt case CEED_EVAL_WEIGHT: 287885ac19cSjeremylt break; // No action 288885ac19cSjeremylt case CEED_EVAL_DIV: 2894d537eeaSYohann break; // Not implemented 290885ac19cSjeremylt case CEED_EVAL_CURL: 2914d537eeaSYohann break; // Not implemented 292885ac19cSjeremylt } 293885ac19cSjeremylt } 294885ac19cSjeremylt // Output pointers 2951a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 296d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 297d1bcdac9Sjeremylt CeedChk(ierr); 298885ac19cSjeremylt if (emode == CEED_EVAL_NONE) { 2994d537eeaSYohann ierr = CeedQFunctionFieldGetSize(qfoutputfields[i], &size); 300d1bcdac9Sjeremylt CeedChk(ierr); 301aedaa0e5Sjeremylt ierr = CeedVectorSetArray(impl->qvecsout[i], CEED_MEM_HOST, 302aedaa0e5Sjeremylt CEED_USE_POINTER, 3034d537eeaSYohann &impl->edata[i + numinputfields][e*Q*size]); 304aedaa0e5Sjeremylt CeedChk(ierr); 305885ac19cSjeremylt } 306885ac19cSjeremylt } 307885ac19cSjeremylt // Q function 308aedaa0e5Sjeremylt ierr = CeedQFunctionApply(qf, Q, impl->qvecsin, impl->qvecsout); CeedChk(ierr); 309885ac19cSjeremylt 310885ac19cSjeremylt // Output basis apply if needed 3111a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 3124d537eeaSYohann // Get elemsize, emode, size 313d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 314d1bcdac9Sjeremylt CeedChk(ierr); 315d1bcdac9Sjeremylt ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize); 316d1bcdac9Sjeremylt CeedChk(ierr); 317d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 318d1bcdac9Sjeremylt CeedChk(ierr); 3194d537eeaSYohann ierr = CeedQFunctionFieldGetSize(qfoutputfields[i], &size); 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, 3294d537eeaSYohann &impl->edata[i + numinputfields][e*elemsize*size]); 330de686571SJeremy L Thompson CeedChk(ierr); 331aedaa0e5Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 332aedaa0e5Sjeremylt CEED_EVAL_INTERP, impl->qvecsout[i], 33391703d3fSjeremylt impl->evecsout[i]); CeedChk(ierr); 334885ac19cSjeremylt break; 335885ac19cSjeremylt case CEED_EVAL_GRAD: 336d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); 337d1bcdac9Sjeremylt CeedChk(ierr); 3384d537eeaSYohann ierr = CeedBasisGetDimension(basis, &dim); CeedChk(ierr); 33991703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsout[i], CEED_MEM_HOST, 340aedaa0e5Sjeremylt CEED_USE_POINTER, 3414d537eeaSYohann &impl->edata[i + numinputfields][e*elemsize*size/dim]); 342de686571SJeremy L Thompson CeedChk(ierr); 343aedaa0e5Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 344aedaa0e5Sjeremylt CEED_EVAL_GRAD, impl->qvecsout[i], 34591703d3fSjeremylt impl->evecsout[i]); CeedChk(ierr); 346885ac19cSjeremylt break; 3474ce2993fSjeremylt case CEED_EVAL_WEIGHT: { 348*c042f62fSJeremy L Thompson // LCOV_EXCL_START 3494ce2993fSjeremylt Ceed ceed; 3504ce2993fSjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 3514ce2993fSjeremylt return CeedError(ceed, 1, 3528d94b059Sjeremylt "CEED_EVAL_WEIGHT cannot be an output evaluation mode"); 353*c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 354885ac19cSjeremylt break; // Should not occur 3554ce2993fSjeremylt } 356885ac19cSjeremylt case CEED_EVAL_DIV: 3578c91a0c9SJeremy L Thompson break; // Not implemented 358885ac19cSjeremylt case CEED_EVAL_CURL: 3598c91a0c9SJeremy L Thompson break; // Not implemented 360885ac19cSjeremylt } 361885ac19cSjeremylt } 362885ac19cSjeremylt } 363885ac19cSjeremylt 36442ecf959Sjeremylt // Zero lvecs 365d1bcdac9Sjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 366d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); 36752d6035fSJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) { 36852d6035fSJeremy L Thompson if (!impl->add) { 369d1bcdac9Sjeremylt vec = outvec; 370d1bcdac9Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 37142ecf959Sjeremylt } 37252d6035fSJeremy L Thompson } else { 37352d6035fSJeremy L Thompson ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 37452d6035fSJeremy L Thompson } 37552d6035fSJeremy L Thompson } 37652d6035fSJeremy L Thompson impl->add = false; 37742ecf959Sjeremylt 378885ac19cSjeremylt // Output restriction 3791a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 380a2b73c81Sjeremylt // Restore evec 381a2b73c81Sjeremylt ierr = CeedVectorRestoreArray(impl->evecs[i+impl->numein], 382d1bcdac9Sjeremylt &impl->edata[i + numinputfields]); 383d1bcdac9Sjeremylt CeedChk(ierr); 384d1bcdac9Sjeremylt // Get output vector 385d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); 386668048e2SJed Brown // Active 387d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 388d1bcdac9Sjeremylt vec = outvec; 3897ca8db16Sjeremylt // Restrict 390d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 391d1bcdac9Sjeremylt CeedChk(ierr); 3924dccadb6Sjeremylt ierr = CeedOperatorFieldGetLMode(opoutputfields[i], &lmode); CeedChk(ierr); 393d1bcdac9Sjeremylt ierr = CeedElemRestrictionApply(Erestrict, CEED_TRANSPOSE, 394d1bcdac9Sjeremylt lmode, impl->evecs[i+impl->numein], vec, 395668048e2SJed Brown request); CeedChk(ierr); 396885ac19cSjeremylt } 397885ac19cSjeremylt 3987ca8db16Sjeremylt // Restore input arrays 3991a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 400d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 401d1bcdac9Sjeremylt CeedChk(ierr); 402135a076eSjeremylt if (emode == CEED_EVAL_WEIGHT) { // Skip 4037ca8db16Sjeremylt } else { 404a2b73c81Sjeremylt ierr = CeedVectorRestoreArrayRead(impl->evecs[i], 405d1bcdac9Sjeremylt (const CeedScalar **) &impl->edata[i]); 406d1bcdac9Sjeremylt CeedChk(ierr); 4077ca8db16Sjeremylt } 4087ca8db16Sjeremylt } 4097ca8db16Sjeremylt 41021617c04Sjeremylt return 0; 41121617c04Sjeremylt } 41221617c04Sjeremylt 41352d6035fSJeremy L Thompson static int CeedCompositeOperatorApply_Ref(CeedOperator op, CeedVector invec, 41452d6035fSJeremy L Thompson CeedVector outvec, 41552d6035fSJeremy L Thompson CeedRequest *request) { 41652d6035fSJeremy L Thompson int ierr; 41752d6035fSJeremy L Thompson CeedInt numsub; 41852d6035fSJeremy L Thompson CeedOperator_Ref *impl; 41952d6035fSJeremy L Thompson CeedOperator *suboperators; 42052d6035fSJeremy L Thompson ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 42152d6035fSJeremy L Thompson ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 42252d6035fSJeremy L Thompson 42352d6035fSJeremy L Thompson // Overwrite outvec with first output 42452d6035fSJeremy L Thompson ierr = CeedOperatorApply(suboperators[0], invec, outvec, request); 42552d6035fSJeremy L Thompson CeedChk(ierr); 42652d6035fSJeremy L Thompson // Add to outvec with subsequent outputs 42752d6035fSJeremy L Thompson for (CeedInt i=1; i<numsub; i++) { 428de686571SJeremy L Thompson ierr = CeedOperatorGetData(suboperators[i], (void *)&impl); CeedChk(ierr); 42952d6035fSJeremy L Thompson impl->add = true; 43052d6035fSJeremy L Thompson ierr = CeedOperatorApply(suboperators[i], invec, outvec, request); 43152d6035fSJeremy L Thompson CeedChk(ierr); 43252d6035fSJeremy L Thompson } 43352d6035fSJeremy L Thompson 43452d6035fSJeremy L Thompson return 0; 43552d6035fSJeremy L Thompson } 43652d6035fSJeremy L Thompson 43721617c04Sjeremylt int CeedOperatorCreate_Ref(CeedOperator op) { 43821617c04Sjeremylt int ierr; 439fe2413ffSjeremylt Ceed ceed; 440fe2413ffSjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 4414ce2993fSjeremylt CeedOperator_Ref *impl; 44221617c04Sjeremylt 44321617c04Sjeremylt ierr = CeedCalloc(1, &impl); CeedChk(ierr); 44452d6035fSJeremy L Thompson impl->add = false; 445de686571SJeremy L Thompson ierr = CeedOperatorSetData(op, (void *)&impl); CeedChk(ierr); 446fe2413ffSjeremylt 447fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "Apply", 448fe2413ffSjeremylt CeedOperatorApply_Ref); CeedChk(ierr); 449fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "Destroy", 450fe2413ffSjeremylt CeedOperatorDestroy_Ref); CeedChk(ierr); 45121617c04Sjeremylt return 0; 45221617c04Sjeremylt } 45352d6035fSJeremy L Thompson 45452d6035fSJeremy L Thompson int CeedCompositeOperatorCreate_Ref(CeedOperator op) { 45552d6035fSJeremy L Thompson int ierr; 45652d6035fSJeremy L Thompson Ceed ceed; 45752d6035fSJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 45852d6035fSJeremy L Thompson 45952d6035fSJeremy L Thompson ierr = CeedSetBackendFunction(ceed, "Operator", op, "Apply", 46052d6035fSJeremy L Thompson CeedCompositeOperatorApply_Ref); CeedChk(ierr); 46152d6035fSJeremy L Thompson return 0; 46252d6035fSJeremy L Thompson } 463