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); 308d713cf6Sjeremylt 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) { 584d1cd9fcSJeremy L Thompson CeedInt dim, ierr, ncomp, P; 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); 994d1cd9fcSJeremy L Thompson ierr = CeedElemRestrictionGetElementSize(Erestrict, &P); 1004d1cd9fcSJeremy L Thompson CeedChk(ierr); 1014d1cd9fcSJeremy L Thompson ierr = CeedVectorCreate(ceed, P*ncomp, &evecs[i]); CeedChk(ierr); 102aedaa0e5Sjeremylt ierr = CeedVectorCreate(ceed, Q*ncomp, &qvecs[i]); CeedChk(ierr); 103885ac19cSjeremylt break; 104885ac19cSjeremylt case CEED_EVAL_GRAD: 105aedaa0e5Sjeremylt ierr = CeedOperatorFieldGetBasis(opfields[i], &basis); CeedChk(ierr); 106aedaa0e5Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qffields[i], &ncomp); 107*de686571SJeremy L Thompson CeedChk(ierr); 108d1bcdac9Sjeremylt ierr = CeedBasisGetDimension(basis, &dim); CeedChk(ierr); 1094d1cd9fcSJeremy L Thompson ierr = CeedElemRestrictionGetElementSize(Erestrict, &P); 1104d1cd9fcSJeremy L Thompson CeedChk(ierr); 1114d1cd9fcSJeremy L Thompson ierr = CeedVectorCreate(ceed, P*ncomp, &evecs[i]); CeedChk(ierr); 112aedaa0e5Sjeremylt ierr = CeedVectorCreate(ceed, Q*ncomp*dim, &qvecs[i]); CeedChk(ierr); 113885ac19cSjeremylt break; 114885ac19cSjeremylt case CEED_EVAL_WEIGHT: // Only on input fields 115aedaa0e5Sjeremylt ierr = CeedOperatorFieldGetBasis(opfields[i], &basis); CeedChk(ierr); 116aedaa0e5Sjeremylt ierr = CeedVectorCreate(ceed, Q, &qvecs[i]); CeedChk(ierr); 117d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 118aedaa0e5Sjeremylt NULL, qvecs[i]); CeedChk(ierr); 119885ac19cSjeremylt break; 120885ac19cSjeremylt case CEED_EVAL_DIV: 121885ac19cSjeremylt break; // Not implimented 122885ac19cSjeremylt case CEED_EVAL_CURL: 123885ac19cSjeremylt break; // Not implimented 12421617c04Sjeremylt } 125885ac19cSjeremylt } 12621617c04Sjeremylt return 0; 12721617c04Sjeremylt } 12821617c04Sjeremylt 129885ac19cSjeremylt /* 130885ac19cSjeremylt CeedOperator needs to connect all the named fields (be they active or passive) 131885ac19cSjeremylt to the named inputs and outputs of its CeedQFunction. 132885ac19cSjeremylt */ 133885ac19cSjeremylt static int CeedOperatorSetup_Ref(CeedOperator op) { 13421617c04Sjeremylt int ierr; 1354ce2993fSjeremylt bool setupdone; 1364ce2993fSjeremylt ierr = CeedOperatorGetSetupStatus(op, &setupdone); CeedChk(ierr); 1374ce2993fSjeremylt if (setupdone) return 0; 138aedaa0e5Sjeremylt Ceed ceed; 139aedaa0e5Sjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 1404ce2993fSjeremylt CeedOperator_Ref *impl; 1414ce2993fSjeremylt ierr = CeedOperatorGetData(op, (void *)&impl); CeedChk(ierr); 1424ce2993fSjeremylt CeedQFunction qf; 1434ce2993fSjeremylt ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 1444ce2993fSjeremylt CeedInt Q, numinputfields, numoutputfields; 1454ce2993fSjeremylt ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 146a8de75f0Sjeremylt ierr = CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 147a8de75f0Sjeremylt CeedChk(ierr); 148d1bcdac9Sjeremylt CeedOperatorField *opinputfields, *opoutputfields; 149d1bcdac9Sjeremylt ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 150d1bcdac9Sjeremylt CeedChk(ierr); 151d1bcdac9Sjeremylt CeedQFunctionField *qfinputfields, *qfoutputfields; 152d1bcdac9Sjeremylt ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 153d1bcdac9Sjeremylt CeedChk(ierr); 154885ac19cSjeremylt 155885ac19cSjeremylt // Allocate 156aedaa0e5Sjeremylt ierr = CeedCalloc(numinputfields + numoutputfields, &impl->evecs); 157aedaa0e5Sjeremylt CeedChk(ierr); 158aedaa0e5Sjeremylt ierr = CeedCalloc(numinputfields + numoutputfields, &impl->edata); 159885ac19cSjeremylt CeedChk(ierr); 160885ac19cSjeremylt 1618d713cf6Sjeremylt ierr = CeedCalloc(16, &impl->inputstate); CeedChk(ierr); 16291703d3fSjeremylt ierr = CeedCalloc(16, &impl->evecsin); CeedChk(ierr); 16391703d3fSjeremylt ierr = CeedCalloc(16, &impl->evecsout); CeedChk(ierr); 164aedaa0e5Sjeremylt ierr = CeedCalloc(16, &impl->qvecsin); CeedChk(ierr); 165aedaa0e5Sjeremylt ierr = CeedCalloc(16, &impl->qvecsout); CeedChk(ierr); 166885ac19cSjeremylt 167aedaa0e5Sjeremylt impl->numein = numinputfields; impl->numeout = numoutputfields; 168885ac19cSjeremylt 169aedaa0e5Sjeremylt // Set up infield and outfield evecs and qvecs 170885ac19cSjeremylt // Infields 17191703d3fSjeremylt ierr = CeedOperatorSetupFields_Ref(qf, op, 0, impl->evecs, 17291703d3fSjeremylt impl->evecsin, impl->qvecsin, 0, 173aedaa0e5Sjeremylt numinputfields, Q); 174aedaa0e5Sjeremylt CeedChk(ierr); 175885ac19cSjeremylt 176885ac19cSjeremylt // Outfields 17791703d3fSjeremylt ierr = CeedOperatorSetupFields_Ref(qf, op, 1, impl->evecs, 17891703d3fSjeremylt impl->evecsout, impl->qvecsout, 179aedaa0e5Sjeremylt numinputfields, numoutputfields, Q); 180d1bcdac9Sjeremylt CeedChk(ierr); 181885ac19cSjeremylt 1824ce2993fSjeremylt ierr = CeedOperatorSetSetupDone(op); CeedChk(ierr); 183885ac19cSjeremylt 184885ac19cSjeremylt return 0; 185885ac19cSjeremylt } 186885ac19cSjeremylt 187885ac19cSjeremylt static int CeedOperatorApply_Ref(CeedOperator op, CeedVector invec, 188885ac19cSjeremylt CeedVector outvec, CeedRequest *request) { 189885ac19cSjeremylt int ierr; 1904ce2993fSjeremylt CeedOperator_Ref *impl; 1914ce2993fSjeremylt ierr = CeedOperatorGetData(op, (void *)&impl); CeedChk(ierr); 1924ce2993fSjeremylt CeedQFunction qf; 1934ce2993fSjeremylt ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 194d1bcdac9Sjeremylt CeedInt Q, numelements, elemsize, numinputfields, numoutputfields, ncomp; 1954ce2993fSjeremylt ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 1964ce2993fSjeremylt ierr = CeedOperatorGetNumElements(op, &numelements); CeedChk(ierr); 1974ce2993fSjeremylt ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 1984ce2993fSjeremylt CeedChk(ierr); 1994dccadb6Sjeremylt CeedTransposeMode lmode; 200d1bcdac9Sjeremylt CeedOperatorField *opinputfields, *opoutputfields; 201d1bcdac9Sjeremylt ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 202d1bcdac9Sjeremylt CeedChk(ierr); 203d1bcdac9Sjeremylt CeedQFunctionField *qfinputfields, *qfoutputfields; 204d1bcdac9Sjeremylt ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 205d1bcdac9Sjeremylt CeedChk(ierr); 206d1bcdac9Sjeremylt CeedEvalMode emode; 207d1bcdac9Sjeremylt CeedVector vec; 208d1bcdac9Sjeremylt CeedBasis basis; 209d1bcdac9Sjeremylt CeedElemRestriction Erestrict; 2108d713cf6Sjeremylt uint64_t state; 211885ac19cSjeremylt 212885ac19cSjeremylt // Setup 213885ac19cSjeremylt ierr = CeedOperatorSetup_Ref(op); CeedChk(ierr); 214885ac19cSjeremylt 215885ac19cSjeremylt // Input Evecs and Restriction 2161a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 217d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 218d1bcdac9Sjeremylt CeedChk(ierr); 219135a076eSjeremylt if (emode == CEED_EVAL_WEIGHT) { // Skip 220668048e2SJed Brown } else { 221d1bcdac9Sjeremylt // Get input vector 222d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opinputfields[i], &vec); CeedChk(ierr); 223d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 224d1bcdac9Sjeremylt vec = invec; 225668048e2SJed Brown // Restrict 2268d713cf6Sjeremylt ierr = CeedVectorGetState(vec, &state); CeedChk(ierr); 2278d713cf6Sjeremylt // Skip restriction if input is unchanged 2288d713cf6Sjeremylt if (state != impl->inputstate[i] || vec == invec) { 229d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); 230d1bcdac9Sjeremylt CeedChk(ierr); 2314dccadb6Sjeremylt ierr = CeedOperatorFieldGetLMode(opinputfields[i], &lmode); CeedChk(ierr); 232d1bcdac9Sjeremylt ierr = CeedElemRestrictionApply(Erestrict, CEED_NOTRANSPOSE, 233d1bcdac9Sjeremylt lmode, vec, impl->evecs[i], 234668048e2SJed Brown request); CeedChk(ierr); 2358d713cf6Sjeremylt impl->inputstate[i] = state; 2368d713cf6Sjeremylt } 237668048e2SJed Brown // Get evec 238a2b73c81Sjeremylt ierr = CeedVectorGetArrayRead(impl->evecs[i], CEED_MEM_HOST, 239d1bcdac9Sjeremylt (const CeedScalar **) &impl->edata[i]); 240d1bcdac9Sjeremylt CeedChk(ierr); 241885ac19cSjeremylt } 242885ac19cSjeremylt } 243885ac19cSjeremylt 244885ac19cSjeremylt // Output Evecs 2451a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 246a2b73c81Sjeremylt ierr = CeedVectorGetArray(impl->evecs[i+impl->numein], CEED_MEM_HOST, 2471a4ead9bSjeremylt &impl->edata[i + numinputfields]); CeedChk(ierr); 248885ac19cSjeremylt } 249885ac19cSjeremylt 250885ac19cSjeremylt // Loop through elements 2514ce2993fSjeremylt for (CeedInt e=0; e<numelements; e++) { 252885ac19cSjeremylt // Input basis apply if needed 2531a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 254135a076eSjeremylt // Get elemsize, emode, ncomp 255d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); 256d1bcdac9Sjeremylt CeedChk(ierr); 257d1bcdac9Sjeremylt ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize); 258d1bcdac9Sjeremylt CeedChk(ierr); 259d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 260d1bcdac9Sjeremylt CeedChk(ierr); 261d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfinputfields[i], &ncomp); 262d1bcdac9Sjeremylt CeedChk(ierr); 263885ac19cSjeremylt // Basis action 264885ac19cSjeremylt switch(emode) { 265885ac19cSjeremylt case CEED_EVAL_NONE: 266aedaa0e5Sjeremylt ierr = CeedVectorSetArray(impl->qvecsin[i], CEED_MEM_HOST, 267aedaa0e5Sjeremylt CEED_USE_POINTER, 268aedaa0e5Sjeremylt &impl->edata[i][e*Q*ncomp]); CeedChk(ierr); 269885ac19cSjeremylt break; 270885ac19cSjeremylt case CEED_EVAL_INTERP: 271d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); CeedChk(ierr); 27291703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsin[i], CEED_MEM_HOST, 273aedaa0e5Sjeremylt CEED_USE_POINTER, 274aedaa0e5Sjeremylt &impl->edata[i][e*elemsize*ncomp]); 275aedaa0e5Sjeremylt CeedChk(ierr); 276d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 27791703d3fSjeremylt CEED_EVAL_INTERP, impl->evecsin[i], 278aedaa0e5Sjeremylt impl->qvecsin[i]); CeedChk(ierr); 279885ac19cSjeremylt break; 280885ac19cSjeremylt case CEED_EVAL_GRAD: 281d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); CeedChk(ierr); 28291703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsin[i], CEED_MEM_HOST, 283aedaa0e5Sjeremylt CEED_USE_POINTER, 284aedaa0e5Sjeremylt &impl->edata[i][e*elemsize*ncomp]); 285aedaa0e5Sjeremylt CeedChk(ierr); 286d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 28791703d3fSjeremylt CEED_EVAL_GRAD, impl->evecsin[i], 288aedaa0e5Sjeremylt impl->qvecsin[i]); CeedChk(ierr); 289885ac19cSjeremylt break; 290885ac19cSjeremylt case CEED_EVAL_WEIGHT: 291885ac19cSjeremylt break; // No action 292885ac19cSjeremylt case CEED_EVAL_DIV: 293885ac19cSjeremylt break; // Not implimented 294885ac19cSjeremylt case CEED_EVAL_CURL: 295885ac19cSjeremylt break; // Not implimented 296885ac19cSjeremylt } 297885ac19cSjeremylt } 298885ac19cSjeremylt // Output pointers 2991a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 300d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 301d1bcdac9Sjeremylt CeedChk(ierr); 302885ac19cSjeremylt if (emode == CEED_EVAL_NONE) { 303d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfoutputfields[i], &ncomp); 304d1bcdac9Sjeremylt CeedChk(ierr); 305aedaa0e5Sjeremylt ierr = CeedVectorSetArray(impl->qvecsout[i], CEED_MEM_HOST, 306aedaa0e5Sjeremylt CEED_USE_POINTER, 307aedaa0e5Sjeremylt &impl->edata[i + numinputfields][e*Q*ncomp]); 308aedaa0e5Sjeremylt CeedChk(ierr); 309885ac19cSjeremylt } 310885ac19cSjeremylt } 311885ac19cSjeremylt // Q function 312aedaa0e5Sjeremylt ierr = CeedQFunctionApply(qf, Q, impl->qvecsin, impl->qvecsout); CeedChk(ierr); 313885ac19cSjeremylt 314885ac19cSjeremylt // Output basis apply if needed 3151a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 316135a076eSjeremylt // Get elemsize, emode, ncomp 317d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 318d1bcdac9Sjeremylt CeedChk(ierr); 319d1bcdac9Sjeremylt ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize); 320d1bcdac9Sjeremylt CeedChk(ierr); 321d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 322d1bcdac9Sjeremylt CeedChk(ierr); 323d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetNumComponents(qfoutputfields[i], &ncomp); 324d1bcdac9Sjeremylt CeedChk(ierr); 325885ac19cSjeremylt // Basis action 326885ac19cSjeremylt switch(emode) { 327885ac19cSjeremylt case CEED_EVAL_NONE: 328885ac19cSjeremylt break; // No action 329885ac19cSjeremylt case CEED_EVAL_INTERP: 330d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); 331d1bcdac9Sjeremylt CeedChk(ierr); 33291703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsout[i], CEED_MEM_HOST, 333aedaa0e5Sjeremylt CEED_USE_POINTER, 3341a4ead9bSjeremylt &impl->edata[i + numinputfields][e*elemsize*ncomp]); 335*de686571SJeremy L Thompson CeedChk(ierr); 336aedaa0e5Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 337aedaa0e5Sjeremylt CEED_EVAL_INTERP, impl->qvecsout[i], 33891703d3fSjeremylt impl->evecsout[i]); CeedChk(ierr); 339885ac19cSjeremylt break; 340885ac19cSjeremylt case CEED_EVAL_GRAD: 341d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); 342d1bcdac9Sjeremylt CeedChk(ierr); 34391703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsout[i], CEED_MEM_HOST, 344aedaa0e5Sjeremylt CEED_USE_POINTER, 345d1bcdac9Sjeremylt &impl->edata[i + numinputfields][e*elemsize*ncomp]); 346*de686571SJeremy L Thompson CeedChk(ierr); 347aedaa0e5Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 348aedaa0e5Sjeremylt CEED_EVAL_GRAD, impl->qvecsout[i], 34991703d3fSjeremylt impl->evecsout[i]); CeedChk(ierr); 350885ac19cSjeremylt break; 3514ce2993fSjeremylt case CEED_EVAL_WEIGHT: { 3524ce2993fSjeremylt Ceed ceed; 3534ce2993fSjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 3544ce2993fSjeremylt return CeedError(ceed, 1, 3558d94b059Sjeremylt "CEED_EVAL_WEIGHT cannot be an output evaluation mode"); 356885ac19cSjeremylt break; // Should not occur 3574ce2993fSjeremylt } 358885ac19cSjeremylt case CEED_EVAL_DIV: 359885ac19cSjeremylt break; // Not implimented 360885ac19cSjeremylt case CEED_EVAL_CURL: 361885ac19cSjeremylt break; // Not implimented 362885ac19cSjeremylt } 363885ac19cSjeremylt } 364885ac19cSjeremylt } 365885ac19cSjeremylt 36642ecf959Sjeremylt // Zero lvecs 367d1bcdac9Sjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 368d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); 36952d6035fSJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) { 37052d6035fSJeremy L Thompson if (!impl->add) { 371d1bcdac9Sjeremylt vec = outvec; 372d1bcdac9Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 37342ecf959Sjeremylt } 37452d6035fSJeremy L Thompson } else { 37552d6035fSJeremy L Thompson ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 37652d6035fSJeremy L Thompson } 37752d6035fSJeremy L Thompson } 37852d6035fSJeremy L Thompson impl->add = false; 37942ecf959Sjeremylt 380885ac19cSjeremylt // Output restriction 3811a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 382a2b73c81Sjeremylt // Restore evec 383a2b73c81Sjeremylt ierr = CeedVectorRestoreArray(impl->evecs[i+impl->numein], 384d1bcdac9Sjeremylt &impl->edata[i + numinputfields]); 385d1bcdac9Sjeremylt CeedChk(ierr); 386d1bcdac9Sjeremylt // Get output vector 387d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); 388668048e2SJed Brown // Active 389d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 390d1bcdac9Sjeremylt vec = outvec; 3917ca8db16Sjeremylt // Restrict 392d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 393d1bcdac9Sjeremylt CeedChk(ierr); 3944dccadb6Sjeremylt ierr = CeedOperatorFieldGetLMode(opoutputfields[i], &lmode); CeedChk(ierr); 395d1bcdac9Sjeremylt ierr = CeedElemRestrictionApply(Erestrict, CEED_TRANSPOSE, 396d1bcdac9Sjeremylt lmode, impl->evecs[i+impl->numein], vec, 397668048e2SJed Brown request); CeedChk(ierr); 398885ac19cSjeremylt } 399885ac19cSjeremylt 4007ca8db16Sjeremylt // Restore input arrays 4011a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 402d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 403d1bcdac9Sjeremylt CeedChk(ierr); 404135a076eSjeremylt if (emode == CEED_EVAL_WEIGHT) { // Skip 4057ca8db16Sjeremylt } else { 406a2b73c81Sjeremylt ierr = CeedVectorRestoreArrayRead(impl->evecs[i], 407d1bcdac9Sjeremylt (const CeedScalar **) &impl->edata[i]); 408d1bcdac9Sjeremylt CeedChk(ierr); 4097ca8db16Sjeremylt } 4107ca8db16Sjeremylt } 4117ca8db16Sjeremylt 41221617c04Sjeremylt return 0; 41321617c04Sjeremylt } 41421617c04Sjeremylt 41552d6035fSJeremy L Thompson static int CeedCompositeOperatorApply_Ref(CeedOperator op, CeedVector invec, 41652d6035fSJeremy L Thompson CeedVector outvec, 41752d6035fSJeremy L Thompson CeedRequest *request) { 41852d6035fSJeremy L Thompson int ierr; 41952d6035fSJeremy L Thompson CeedInt numsub; 42052d6035fSJeremy L Thompson CeedOperator_Ref *impl; 42152d6035fSJeremy L Thompson CeedOperator *suboperators; 42252d6035fSJeremy L Thompson ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 42352d6035fSJeremy L Thompson ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 42452d6035fSJeremy L Thompson 42552d6035fSJeremy L Thompson // Overwrite outvec with first output 42652d6035fSJeremy L Thompson ierr = CeedOperatorApply(suboperators[0], invec, outvec, request); 42752d6035fSJeremy L Thompson CeedChk(ierr); 42852d6035fSJeremy L Thompson // Add to outvec with subsequent outputs 42952d6035fSJeremy L Thompson for (CeedInt i=1; i<numsub; i++) { 430*de686571SJeremy L Thompson ierr = CeedOperatorGetData(suboperators[i], (void *)&impl); CeedChk(ierr); 43152d6035fSJeremy L Thompson impl->add = true; 43252d6035fSJeremy L Thompson ierr = CeedOperatorApply(suboperators[i], invec, outvec, request); 43352d6035fSJeremy L Thompson CeedChk(ierr); 43452d6035fSJeremy L Thompson } 43552d6035fSJeremy L Thompson 43652d6035fSJeremy L Thompson return 0; 43752d6035fSJeremy L Thompson } 43852d6035fSJeremy L Thompson 43921617c04Sjeremylt int CeedOperatorCreate_Ref(CeedOperator op) { 44021617c04Sjeremylt int ierr; 441fe2413ffSjeremylt Ceed ceed; 442fe2413ffSjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 4434ce2993fSjeremylt CeedOperator_Ref *impl; 44421617c04Sjeremylt 44521617c04Sjeremylt ierr = CeedCalloc(1, &impl); CeedChk(ierr); 44652d6035fSJeremy L Thompson impl->add = false; 447*de686571SJeremy L Thompson ierr = CeedOperatorSetData(op, (void *)&impl); CeedChk(ierr); 448fe2413ffSjeremylt 449fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "Apply", 450fe2413ffSjeremylt CeedOperatorApply_Ref); CeedChk(ierr); 451fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "Destroy", 452fe2413ffSjeremylt CeedOperatorDestroy_Ref); CeedChk(ierr); 45321617c04Sjeremylt return 0; 45421617c04Sjeremylt } 45552d6035fSJeremy L Thompson 45652d6035fSJeremy L Thompson int CeedCompositeOperatorCreate_Ref(CeedOperator op) { 45752d6035fSJeremy L Thompson int ierr; 45852d6035fSJeremy L Thompson Ceed ceed; 45952d6035fSJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 46052d6035fSJeremy L Thompson 46152d6035fSJeremy L Thompson ierr = CeedSetBackendFunction(ceed, "Operator", op, "Apply", 46252d6035fSJeremy L Thompson CeedCompositeOperatorApply_Ref); CeedChk(ierr); 46352d6035fSJeremy L Thompson return 0; 46452d6035fSJeremy L Thompson } 465