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); 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]); 334aedaa0e5Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 335aedaa0e5Sjeremylt CEED_EVAL_INTERP, impl->qvecsout[i], 33691703d3fSjeremylt impl->evecsout[i]); CeedChk(ierr); 337885ac19cSjeremylt break; 338885ac19cSjeremylt case CEED_EVAL_GRAD: 339d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); 340d1bcdac9Sjeremylt CeedChk(ierr); 34191703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsout[i], CEED_MEM_HOST, 342aedaa0e5Sjeremylt CEED_USE_POINTER, 343d1bcdac9Sjeremylt &impl->edata[i + numinputfields][e*elemsize*ncomp]); 344aedaa0e5Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 345aedaa0e5Sjeremylt CEED_EVAL_GRAD, impl->qvecsout[i], 34691703d3fSjeremylt impl->evecsout[i]); CeedChk(ierr); 347885ac19cSjeremylt break; 3484ce2993fSjeremylt case CEED_EVAL_WEIGHT: { 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"); 353885ac19cSjeremylt break; // Should not occur 3544ce2993fSjeremylt } 355885ac19cSjeremylt case CEED_EVAL_DIV: 356885ac19cSjeremylt break; // Not implimented 357885ac19cSjeremylt case CEED_EVAL_CURL: 358885ac19cSjeremylt break; // Not implimented 359885ac19cSjeremylt } 360885ac19cSjeremylt } 361885ac19cSjeremylt } 362885ac19cSjeremylt 36342ecf959Sjeremylt // Zero lvecs 364d1bcdac9Sjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 365d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); 366*52d6035fSJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) { 367*52d6035fSJeremy L Thompson if (!impl->add) { 368d1bcdac9Sjeremylt vec = outvec; 369d1bcdac9Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 37042ecf959Sjeremylt } 371*52d6035fSJeremy L Thompson } else { 372*52d6035fSJeremy L Thompson ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 373*52d6035fSJeremy L Thompson } 374*52d6035fSJeremy L Thompson } 375*52d6035fSJeremy L Thompson impl->add = false; 37642ecf959Sjeremylt 377885ac19cSjeremylt // Output restriction 3781a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 379a2b73c81Sjeremylt // Restore evec 380a2b73c81Sjeremylt ierr = CeedVectorRestoreArray(impl->evecs[i+impl->numein], 381d1bcdac9Sjeremylt &impl->edata[i + numinputfields]); 382d1bcdac9Sjeremylt CeedChk(ierr); 383d1bcdac9Sjeremylt // Get output vector 384d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr); 385668048e2SJed Brown // Active 386d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 387d1bcdac9Sjeremylt vec = outvec; 3887ca8db16Sjeremylt // Restrict 389d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 390d1bcdac9Sjeremylt CeedChk(ierr); 3914dccadb6Sjeremylt ierr = CeedOperatorFieldGetLMode(opoutputfields[i], &lmode); CeedChk(ierr); 392d1bcdac9Sjeremylt ierr = CeedElemRestrictionApply(Erestrict, CEED_TRANSPOSE, 393d1bcdac9Sjeremylt lmode, impl->evecs[i+impl->numein], vec, 394668048e2SJed Brown request); CeedChk(ierr); 395885ac19cSjeremylt } 396885ac19cSjeremylt 3977ca8db16Sjeremylt // Restore input arrays 3981a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 399d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 400d1bcdac9Sjeremylt CeedChk(ierr); 401135a076eSjeremylt if (emode == CEED_EVAL_WEIGHT) { // Skip 4027ca8db16Sjeremylt } else { 403a2b73c81Sjeremylt ierr = CeedVectorRestoreArrayRead(impl->evecs[i], 404d1bcdac9Sjeremylt (const CeedScalar **) &impl->edata[i]); 405d1bcdac9Sjeremylt CeedChk(ierr); 4067ca8db16Sjeremylt } 4077ca8db16Sjeremylt } 4087ca8db16Sjeremylt 40921617c04Sjeremylt return 0; 41021617c04Sjeremylt } 41121617c04Sjeremylt 412*52d6035fSJeremy L Thompson static int CeedCompositeOperatorApply_Ref(CeedOperator op, CeedVector invec, 413*52d6035fSJeremy L Thompson CeedVector outvec, 414*52d6035fSJeremy L Thompson CeedRequest *request) { 415*52d6035fSJeremy L Thompson int ierr; 416*52d6035fSJeremy L Thompson CeedInt numsub; 417*52d6035fSJeremy L Thompson CeedOperator_Ref *impl; 418*52d6035fSJeremy L Thompson CeedOperator *suboperators; 419*52d6035fSJeremy L Thompson ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 420*52d6035fSJeremy L Thompson ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 421*52d6035fSJeremy L Thompson 422*52d6035fSJeremy L Thompson // Overwrite outvec with first output 423*52d6035fSJeremy L Thompson ierr = CeedOperatorApply(suboperators[0], invec, outvec, request); 424*52d6035fSJeremy L Thompson CeedChk(ierr); 425*52d6035fSJeremy L Thompson // Add to outvec with subsequent outputs 426*52d6035fSJeremy L Thompson for (CeedInt i=1; i<numsub; i++) { 427*52d6035fSJeremy L Thompson ierr = CeedOperatorGetData(suboperators[i], (void *)&impl); 428*52d6035fSJeremy L Thompson impl->add = true; 429*52d6035fSJeremy L Thompson ierr = CeedOperatorApply(suboperators[i], invec, outvec, request); 430*52d6035fSJeremy L Thompson CeedChk(ierr); 431*52d6035fSJeremy L Thompson } 432*52d6035fSJeremy L Thompson 433*52d6035fSJeremy L Thompson return 0; 434*52d6035fSJeremy L Thompson } 435*52d6035fSJeremy L Thompson 43621617c04Sjeremylt int CeedOperatorCreate_Ref(CeedOperator op) { 43721617c04Sjeremylt int ierr; 438fe2413ffSjeremylt Ceed ceed; 439fe2413ffSjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 4404ce2993fSjeremylt CeedOperator_Ref *impl; 44121617c04Sjeremylt 44221617c04Sjeremylt ierr = CeedCalloc(1, &impl); CeedChk(ierr); 443*52d6035fSJeremy L Thompson impl->add = false; 444fe2413ffSjeremylt ierr = CeedOperatorSetData(op, (void *)&impl); 445fe2413ffSjeremylt 446fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "Apply", 447fe2413ffSjeremylt CeedOperatorApply_Ref); CeedChk(ierr); 448fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "Destroy", 449fe2413ffSjeremylt CeedOperatorDestroy_Ref); CeedChk(ierr); 45021617c04Sjeremylt return 0; 45121617c04Sjeremylt } 452*52d6035fSJeremy L Thompson 453*52d6035fSJeremy L Thompson int CeedCompositeOperatorCreate_Ref(CeedOperator op) { 454*52d6035fSJeremy L Thompson int ierr; 455*52d6035fSJeremy L Thompson Ceed ceed; 456*52d6035fSJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 457*52d6035fSJeremy L Thompson 458*52d6035fSJeremy L Thompson ierr = CeedSetBackendFunction(ceed, "Operator", op, "Apply", 459*52d6035fSJeremy L Thompson CeedCompositeOperatorApply_Ref); CeedChk(ierr); 460*52d6035fSJeremy L Thompson return 0; 461*52d6035fSJeremy L Thompson } 462