xref: /libCEED/backends/ref/ceed-ref-operator.c (revision aedaa0e5fd3a3e03ad33ad8a6308ac527f4f900e)
121617c04Sjeremylt // Copyright (c) 2017-2018, Lawrence Livermore National Security, LLC.
221617c04Sjeremylt // Produced at the Lawrence Livermore National Laboratory. LLNL-CODE-734707.
321617c04Sjeremylt // All Rights reserved. See files LICENSE and NOTICE for details.
421617c04Sjeremylt //
521617c04Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software
621617c04Sjeremylt // libraries and APIs for efficient high-order finite element and spectral
721617c04Sjeremylt // element discretizations for exascale applications. For more information and
821617c04Sjeremylt // source code availability see http://github.com/ceed.
921617c04Sjeremylt //
1021617c04Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
1121617c04Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office
1221617c04Sjeremylt // of Science and the National Nuclear Security Administration) responsible for
1321617c04Sjeremylt // the planning and preparation of a capable exascale ecosystem, including
1421617c04Sjeremylt // software, applications, hardware, advanced system engineering and early
1521617c04Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative.
1621617c04Sjeremylt 
1721617c04Sjeremylt #include <string.h>
1821617c04Sjeremylt #include "ceed-ref.h"
1921617c04Sjeremylt 
2021617c04Sjeremylt static int CeedOperatorDestroy_Ref(CeedOperator op) {
2121617c04Sjeremylt   int ierr;
224ce2993fSjeremylt   CeedOperator_Ref *impl;
234ce2993fSjeremylt   ierr = CeedOperatorGetData(op, (void*)&impl); CeedChk(ierr);
2421617c04Sjeremylt 
25885ac19cSjeremylt   for (CeedInt i=0; i<impl->numein+impl->numeout; i++) {
26885ac19cSjeremylt     ierr = CeedVectorDestroy(&impl->evecs[i]); CeedChk(ierr);
27885ac19cSjeremylt   }
28885ac19cSjeremylt   ierr = CeedFree(&impl->evecs); CeedChk(ierr);
29885ac19cSjeremylt   ierr = CeedFree(&impl->edata); CeedChk(ierr);
30885ac19cSjeremylt 
31*aedaa0e5Sjeremylt   for (CeedInt i=0; i<impl->numein; i++) {
32*aedaa0e5Sjeremylt     ierr = CeedVectorDestroy(&impl->qvecsin[i]); CeedChk(ierr);
33885ac19cSjeremylt   }
34*aedaa0e5Sjeremylt   ierr = CeedFree(&impl->qvecsin); CeedChk(ierr);
35885ac19cSjeremylt 
36*aedaa0e5Sjeremylt   for (CeedInt i=0; i<impl->numeout; i++) {
37*aedaa0e5Sjeremylt     ierr = CeedVectorDestroy(&impl->qvecsout[i]); CeedChk(ierr);
38*aedaa0e5Sjeremylt   }
39*aedaa0e5Sjeremylt   ierr = CeedFree(&impl->qvecsout); CeedChk(ierr);
40885ac19cSjeremylt 
41fe2413ffSjeremylt   ierr = CeedFree(&impl); CeedChk(ierr);
4221617c04Sjeremylt   return 0;
4321617c04Sjeremylt }
4421617c04Sjeremylt 
45885ac19cSjeremylt /*
46885ac19cSjeremylt   Setup infields or outfields
47885ac19cSjeremylt  */
48fe2413ffSjeremylt static int CeedOperatorSetupFields_Ref(CeedQFunction qf, CeedOperator op,
49*aedaa0e5Sjeremylt                                        bool inOrOut, CeedVector *evecs,
50*aedaa0e5Sjeremylt                                        CeedVector *qvecs, CeedInt starte,
51135a076eSjeremylt                                        CeedInt numfields, CeedInt Q) {
52*aedaa0e5Sjeremylt   CeedInt dim, ierr, ncomp;
53*aedaa0e5Sjeremylt   Ceed ceed;
54*aedaa0e5Sjeremylt   ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
55d1bcdac9Sjeremylt   CeedBasis basis;
56d1bcdac9Sjeremylt   CeedElemRestriction Erestrict;
57*aedaa0e5Sjeremylt   CeedOperatorField *opfields;
58*aedaa0e5Sjeremylt   CeedQFunctionField *qffields;
59fe2413ffSjeremylt   if (inOrOut) {
60*aedaa0e5Sjeremylt     ierr = CeedOperatorGetFields(op, NULL, &opfields);
61fe2413ffSjeremylt     CeedChk(ierr);
62*aedaa0e5Sjeremylt     ierr = CeedQFunctionGetFields(qf, NULL, &qffields);
63fe2413ffSjeremylt     CeedChk(ierr);
64fe2413ffSjeremylt   } else {
65*aedaa0e5Sjeremylt     ierr = CeedOperatorGetFields(op, &opfields, NULL);
66fe2413ffSjeremylt     CeedChk(ierr);
67*aedaa0e5Sjeremylt     ierr = CeedQFunctionGetFields(qf, &qffields, NULL);
68fe2413ffSjeremylt     CeedChk(ierr);
69fe2413ffSjeremylt   }
7021617c04Sjeremylt 
71885ac19cSjeremylt   // Loop over fields
72885ac19cSjeremylt   for (CeedInt i=0; i<numfields; i++) {
73d1bcdac9Sjeremylt     CeedEvalMode emode;
74*aedaa0e5Sjeremylt     ierr = CeedQFunctionFieldGetEvalMode(qffields[i], &emode); CeedChk(ierr);
75135a076eSjeremylt 
76135a076eSjeremylt     if (emode != CEED_EVAL_WEIGHT) {
77*aedaa0e5Sjeremylt       ierr = CeedOperatorFieldGetElemRestriction(opfields[i], &Erestrict);
78d1bcdac9Sjeremylt       CeedChk(ierr);
79d1bcdac9Sjeremylt       ierr = CeedElemRestrictionCreateVector(Erestrict, NULL,
80*aedaa0e5Sjeremylt                                              &evecs[i+starte]);
81135a076eSjeremylt       CeedChk(ierr);
82135a076eSjeremylt     }
83135a076eSjeremylt 
84885ac19cSjeremylt     switch(emode) {
85885ac19cSjeremylt     case CEED_EVAL_NONE:
86*aedaa0e5Sjeremylt       ierr = CeedQFunctionFieldGetNumComponents(qffields[i], &ncomp);
87d1bcdac9Sjeremylt       CeedChk(ierr);
88*aedaa0e5Sjeremylt       ierr = CeedVectorCreate(ceed, Q*ncomp, &qvecs[i]); CeedChk(ierr);
89*aedaa0e5Sjeremylt       break;
90*aedaa0e5Sjeremylt     case CEED_EVAL_INTERP:
91*aedaa0e5Sjeremylt       ierr = CeedQFunctionFieldGetNumComponents(qffields[i], &ncomp);
92*aedaa0e5Sjeremylt       CeedChk(ierr);
93*aedaa0e5Sjeremylt       ierr = CeedVectorCreate(ceed, Q*ncomp, &qvecs[i]); CeedChk(ierr);
94885ac19cSjeremylt       break;
95885ac19cSjeremylt     case CEED_EVAL_GRAD:
96*aedaa0e5Sjeremylt       ierr = CeedOperatorFieldGetBasis(opfields[i], &basis); CeedChk(ierr);
97*aedaa0e5Sjeremylt       ierr = CeedQFunctionFieldGetNumComponents(qffields[i], &ncomp);
98d1bcdac9Sjeremylt       ierr = CeedBasisGetDimension(basis, &dim); CeedChk(ierr);
99*aedaa0e5Sjeremylt       ierr = CeedVectorCreate(ceed, Q*ncomp*dim, &qvecs[i]); CeedChk(ierr);
100885ac19cSjeremylt       break;
101885ac19cSjeremylt     case CEED_EVAL_WEIGHT: // Only on input fields
102*aedaa0e5Sjeremylt       ierr = CeedOperatorFieldGetBasis(opfields[i], &basis); CeedChk(ierr);
103*aedaa0e5Sjeremylt       ierr = CeedVectorCreate(ceed, Q, &qvecs[i]); CeedChk(ierr);
104d1bcdac9Sjeremylt       ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT,
105*aedaa0e5Sjeremylt                             NULL, qvecs[i]); CeedChk(ierr);
106885ac19cSjeremylt       break;
107885ac19cSjeremylt     case CEED_EVAL_DIV:
108885ac19cSjeremylt       break; // Not implimented
109885ac19cSjeremylt     case CEED_EVAL_CURL:
110885ac19cSjeremylt       break; // Not implimented
11121617c04Sjeremylt     }
112885ac19cSjeremylt   }
11321617c04Sjeremylt   return 0;
11421617c04Sjeremylt }
11521617c04Sjeremylt 
116885ac19cSjeremylt /*
117885ac19cSjeremylt   CeedOperator needs to connect all the named fields (be they active or passive)
118885ac19cSjeremylt   to the named inputs and outputs of its CeedQFunction.
119885ac19cSjeremylt  */
120885ac19cSjeremylt static int CeedOperatorSetup_Ref(CeedOperator op) {
12121617c04Sjeremylt   int ierr;
1224ce2993fSjeremylt   bool setupdone;
1234ce2993fSjeremylt   ierr = CeedOperatorGetSetupStatus(op, &setupdone); CeedChk(ierr);
1244ce2993fSjeremylt   if (setupdone) return 0;
125*aedaa0e5Sjeremylt   Ceed ceed;
126*aedaa0e5Sjeremylt   ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
1274ce2993fSjeremylt   CeedOperator_Ref *impl;
1284ce2993fSjeremylt   ierr = CeedOperatorGetData(op, (void*)&impl); CeedChk(ierr);
1294ce2993fSjeremylt   CeedQFunction qf;
1304ce2993fSjeremylt   ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr);
1314ce2993fSjeremylt   CeedInt Q, numinputfields, numoutputfields;
1324ce2993fSjeremylt   ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr);
133a8de75f0Sjeremylt   ierr = CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields);
134a8de75f0Sjeremylt   CeedChk(ierr);
135d1bcdac9Sjeremylt   CeedOperatorField *opinputfields, *opoutputfields;
136d1bcdac9Sjeremylt   ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields);
137d1bcdac9Sjeremylt   CeedChk(ierr);
138d1bcdac9Sjeremylt   CeedQFunctionField *qfinputfields, *qfoutputfields;
139d1bcdac9Sjeremylt   ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields);
140d1bcdac9Sjeremylt   CeedChk(ierr);
141885ac19cSjeremylt 
142885ac19cSjeremylt   // Allocate
143*aedaa0e5Sjeremylt   ierr = CeedCalloc(numinputfields + numoutputfields, &impl->evecs);
144*aedaa0e5Sjeremylt   CeedChk(ierr);
145*aedaa0e5Sjeremylt   ierr = CeedCalloc(numinputfields + numoutputfields, &impl->edata);
146885ac19cSjeremylt   CeedChk(ierr);
147885ac19cSjeremylt 
148*aedaa0e5Sjeremylt   ierr = CeedCalloc(16, &impl->qvecsin); CeedChk(ierr);
149*aedaa0e5Sjeremylt   ierr = CeedCalloc(16, &impl->qvecsout); CeedChk(ierr);
150885ac19cSjeremylt 
151*aedaa0e5Sjeremylt   impl->numein = numinputfields; impl->numeout = numoutputfields;
152885ac19cSjeremylt 
153*aedaa0e5Sjeremylt   // Set up infield and outfield evecs and qvecs
154885ac19cSjeremylt   // Infields
155fe2413ffSjeremylt   ierr = CeedOperatorSetupFields_Ref(qf, op, 0,
156*aedaa0e5Sjeremylt                                      impl->evecs, impl->qvecsin, 0,
157*aedaa0e5Sjeremylt                                      numinputfields, Q);
158*aedaa0e5Sjeremylt   CeedChk(ierr);
159885ac19cSjeremylt 
160885ac19cSjeremylt   // Outfields
161fe2413ffSjeremylt   ierr = CeedOperatorSetupFields_Ref(qf, op, 1,
162*aedaa0e5Sjeremylt                                      impl->evecs, impl->qvecsout,
163*aedaa0e5Sjeremylt                                      numinputfields, numoutputfields, Q);
164d1bcdac9Sjeremylt   CeedChk(ierr);
165885ac19cSjeremylt 
166*aedaa0e5Sjeremylt   // Temporary Vector
167*aedaa0e5Sjeremylt   ierr = CeedVectorCreate(ceed, 0, &impl->tempvec); CeedChk(ierr);
1687ca8db16Sjeremylt 
1694ce2993fSjeremylt   ierr = CeedOperatorSetSetupDone(op); CeedChk(ierr);
170885ac19cSjeremylt 
171885ac19cSjeremylt   return 0;
172885ac19cSjeremylt }
173885ac19cSjeremylt 
174885ac19cSjeremylt static int CeedOperatorApply_Ref(CeedOperator op, CeedVector invec,
175885ac19cSjeremylt                                  CeedVector outvec, CeedRequest *request) {
176885ac19cSjeremylt   int ierr;
1774ce2993fSjeremylt   CeedOperator_Ref *impl;
1784ce2993fSjeremylt   ierr = CeedOperatorGetData(op, (void*)&impl); CeedChk(ierr);
1794ce2993fSjeremylt   CeedQFunction qf;
1804ce2993fSjeremylt   ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr);
181d1bcdac9Sjeremylt   CeedInt Q, numelements, elemsize, numinputfields, numoutputfields, ncomp;
1824ce2993fSjeremylt   ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr);
1834ce2993fSjeremylt   ierr = CeedOperatorGetNumElements(op, &numelements); CeedChk(ierr);
1844ce2993fSjeremylt   ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields);
1854ce2993fSjeremylt   CeedChk(ierr);
1864dccadb6Sjeremylt   CeedTransposeMode lmode;
187d1bcdac9Sjeremylt   CeedOperatorField *opinputfields, *opoutputfields;
188d1bcdac9Sjeremylt   ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields);
189d1bcdac9Sjeremylt   CeedChk(ierr);
190d1bcdac9Sjeremylt   CeedQFunctionField *qfinputfields, *qfoutputfields;
191d1bcdac9Sjeremylt   ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields);
192d1bcdac9Sjeremylt   CeedChk(ierr);
193d1bcdac9Sjeremylt   CeedEvalMode emode;
194d1bcdac9Sjeremylt   CeedVector vec;
195d1bcdac9Sjeremylt   CeedBasis basis;
196d1bcdac9Sjeremylt   CeedElemRestriction Erestrict;
197885ac19cSjeremylt 
198885ac19cSjeremylt   // Setup
199885ac19cSjeremylt   ierr = CeedOperatorSetup_Ref(op); CeedChk(ierr);
200885ac19cSjeremylt 
201885ac19cSjeremylt   // Input Evecs and Restriction
2021a4ead9bSjeremylt   for (CeedInt i=0; i<numinputfields; i++) {
203d1bcdac9Sjeremylt     ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode);
204d1bcdac9Sjeremylt     CeedChk(ierr);
205135a076eSjeremylt     if (emode == CEED_EVAL_WEIGHT) { // Skip
206668048e2SJed Brown     } else {
207d1bcdac9Sjeremylt       // Get input vector
208d1bcdac9Sjeremylt       ierr = CeedOperatorFieldGetVector(opinputfields[i], &vec); CeedChk(ierr);
209d1bcdac9Sjeremylt       if (vec == CEED_VECTOR_ACTIVE)
210d1bcdac9Sjeremylt         vec = invec;
211668048e2SJed Brown       // Restrict
212d1bcdac9Sjeremylt       ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict);
213d1bcdac9Sjeremylt       CeedChk(ierr);
2144dccadb6Sjeremylt       ierr = CeedOperatorFieldGetLMode(opinputfields[i], &lmode); CeedChk(ierr);
215d1bcdac9Sjeremylt       ierr = CeedElemRestrictionApply(Erestrict, CEED_NOTRANSPOSE,
216d1bcdac9Sjeremylt                                       lmode, vec, impl->evecs[i],
217668048e2SJed Brown                                       request); CeedChk(ierr);
218668048e2SJed Brown       // Get evec
219a2b73c81Sjeremylt       ierr = CeedVectorGetArrayRead(impl->evecs[i], CEED_MEM_HOST,
220d1bcdac9Sjeremylt                                     (const CeedScalar **) &impl->edata[i]);
221d1bcdac9Sjeremylt       CeedChk(ierr);
222885ac19cSjeremylt     }
223885ac19cSjeremylt   }
224885ac19cSjeremylt 
225885ac19cSjeremylt   // Output Evecs
2261a4ead9bSjeremylt   for (CeedInt i=0; i<numoutputfields; i++) {
227a2b73c81Sjeremylt     ierr = CeedVectorGetArray(impl->evecs[i+impl->numein], CEED_MEM_HOST,
2281a4ead9bSjeremylt                               &impl->edata[i + numinputfields]); CeedChk(ierr);
229885ac19cSjeremylt   }
230885ac19cSjeremylt 
231885ac19cSjeremylt   // Loop through elements
2324ce2993fSjeremylt   for (CeedInt e=0; e<numelements; e++) {
233885ac19cSjeremylt     // Input basis apply if needed
2341a4ead9bSjeremylt     for (CeedInt i=0; i<numinputfields; i++) {
235135a076eSjeremylt       // Get elemsize, emode, ncomp
236d1bcdac9Sjeremylt       ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict);
237d1bcdac9Sjeremylt       CeedChk(ierr);
238d1bcdac9Sjeremylt       ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize);
239d1bcdac9Sjeremylt       CeedChk(ierr);
240d1bcdac9Sjeremylt       ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode);
241d1bcdac9Sjeremylt       CeedChk(ierr);
242d1bcdac9Sjeremylt       ierr = CeedQFunctionFieldGetNumComponents(qfinputfields[i], &ncomp);
243d1bcdac9Sjeremylt       CeedChk(ierr);
244885ac19cSjeremylt       // Basis action
245885ac19cSjeremylt       switch(emode) {
246885ac19cSjeremylt       case CEED_EVAL_NONE:
247*aedaa0e5Sjeremylt         ierr = CeedVectorSetArray(impl->qvecsin[i], CEED_MEM_HOST,
248*aedaa0e5Sjeremylt                                   CEED_USE_POINTER,
249*aedaa0e5Sjeremylt                                   &impl->edata[i][e*Q*ncomp]); CeedChk(ierr);
250885ac19cSjeremylt         break;
251885ac19cSjeremylt       case CEED_EVAL_INTERP:
252d1bcdac9Sjeremylt         ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); CeedChk(ierr);
253*aedaa0e5Sjeremylt         ierr = CeedVectorSetArray(impl->tempvec, CEED_MEM_HOST,
254*aedaa0e5Sjeremylt                                   CEED_USE_POINTER,
255*aedaa0e5Sjeremylt                                   &impl->edata[i][e*elemsize*ncomp]);
256*aedaa0e5Sjeremylt         CeedChk(ierr);
257d1bcdac9Sjeremylt         ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE,
258*aedaa0e5Sjeremylt                               CEED_EVAL_INTERP, impl->tempvec,
259*aedaa0e5Sjeremylt                               impl->qvecsin[i]); CeedChk(ierr);
260885ac19cSjeremylt         break;
261885ac19cSjeremylt       case CEED_EVAL_GRAD:
262d1bcdac9Sjeremylt         ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); CeedChk(ierr);
263*aedaa0e5Sjeremylt         ierr = CeedVectorSetArray(impl->tempvec, CEED_MEM_HOST,
264*aedaa0e5Sjeremylt                                   CEED_USE_POINTER,
265*aedaa0e5Sjeremylt                                   &impl->edata[i][e*elemsize*ncomp]);
266*aedaa0e5Sjeremylt         CeedChk(ierr);
267d1bcdac9Sjeremylt         ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE,
268*aedaa0e5Sjeremylt                               CEED_EVAL_GRAD, impl->tempvec,
269*aedaa0e5Sjeremylt                               impl->qvecsin[i]); CeedChk(ierr);
270885ac19cSjeremylt         break;
271885ac19cSjeremylt       case CEED_EVAL_WEIGHT:
272885ac19cSjeremylt         break;  // No action
273885ac19cSjeremylt       case CEED_EVAL_DIV:
274885ac19cSjeremylt         break; // Not implimented
275885ac19cSjeremylt       case CEED_EVAL_CURL:
276885ac19cSjeremylt         break; // Not implimented
277885ac19cSjeremylt       }
278885ac19cSjeremylt     }
279885ac19cSjeremylt     // Output pointers
2801a4ead9bSjeremylt     for (CeedInt i=0; i<numoutputfields; i++) {
281d1bcdac9Sjeremylt       ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode);
282d1bcdac9Sjeremylt       CeedChk(ierr);
283885ac19cSjeremylt       if (emode == CEED_EVAL_NONE) {
284d1bcdac9Sjeremylt         ierr = CeedQFunctionFieldGetNumComponents(qfoutputfields[i], &ncomp);
285d1bcdac9Sjeremylt         CeedChk(ierr);
286*aedaa0e5Sjeremylt         ierr = CeedVectorSetArray(impl->qvecsout[i], CEED_MEM_HOST,
287*aedaa0e5Sjeremylt                                   CEED_USE_POINTER,
288*aedaa0e5Sjeremylt                                   &impl->edata[i + numinputfields][e*Q*ncomp]);
289*aedaa0e5Sjeremylt         CeedChk(ierr);
290885ac19cSjeremylt       }
291885ac19cSjeremylt     }
292885ac19cSjeremylt     // Q function
293*aedaa0e5Sjeremylt     ierr = CeedQFunctionApply(qf, Q, impl->qvecsin, impl->qvecsout); CeedChk(ierr);
294885ac19cSjeremylt 
295885ac19cSjeremylt     // Output basis apply if needed
2961a4ead9bSjeremylt     for (CeedInt i=0; i<numoutputfields; i++) {
297135a076eSjeremylt       // Get elemsize, emode, ncomp
298d1bcdac9Sjeremylt       ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict);
299d1bcdac9Sjeremylt       CeedChk(ierr);
300d1bcdac9Sjeremylt       ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize);
301d1bcdac9Sjeremylt       CeedChk(ierr);
302d1bcdac9Sjeremylt       ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode);
303d1bcdac9Sjeremylt       CeedChk(ierr);
304d1bcdac9Sjeremylt       ierr = CeedQFunctionFieldGetNumComponents(qfoutputfields[i], &ncomp);
305d1bcdac9Sjeremylt       CeedChk(ierr);
306885ac19cSjeremylt       // Basis action
307885ac19cSjeremylt       switch(emode) {
308885ac19cSjeremylt       case CEED_EVAL_NONE:
309885ac19cSjeremylt         break; // No action
310885ac19cSjeremylt       case CEED_EVAL_INTERP:
311d1bcdac9Sjeremylt         ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis);
312d1bcdac9Sjeremylt         CeedChk(ierr);
313*aedaa0e5Sjeremylt         ierr = CeedVectorSetArray(impl->tempvec, CEED_MEM_HOST,
314*aedaa0e5Sjeremylt                                   CEED_USE_POINTER,
3151a4ead9bSjeremylt                                   &impl->edata[i + numinputfields][e*elemsize*ncomp]);
316*aedaa0e5Sjeremylt         ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE,
317*aedaa0e5Sjeremylt                               CEED_EVAL_INTERP, impl->qvecsout[i],
318*aedaa0e5Sjeremylt                               impl->tempvec); CeedChk(ierr);
319885ac19cSjeremylt         break;
320885ac19cSjeremylt       case CEED_EVAL_GRAD:
321d1bcdac9Sjeremylt         ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis);
322d1bcdac9Sjeremylt         CeedChk(ierr);
323*aedaa0e5Sjeremylt         ierr = CeedVectorSetArray(impl->tempvec, CEED_MEM_HOST,
324*aedaa0e5Sjeremylt                                   CEED_USE_POINTER,
325d1bcdac9Sjeremylt                                   &impl->edata[i + numinputfields][e*elemsize*ncomp]);
326*aedaa0e5Sjeremylt         ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE,
327*aedaa0e5Sjeremylt                               CEED_EVAL_GRAD, impl->qvecsout[i],
328*aedaa0e5Sjeremylt                               impl->tempvec); CeedChk(ierr);
329885ac19cSjeremylt         break;
3304ce2993fSjeremylt       case CEED_EVAL_WEIGHT: {
3314ce2993fSjeremylt         Ceed ceed;
3324ce2993fSjeremylt         ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
3334ce2993fSjeremylt         return CeedError(ceed, 1,
3348d94b059Sjeremylt                          "CEED_EVAL_WEIGHT cannot be an output evaluation mode");
335885ac19cSjeremylt         break; // Should not occur
3364ce2993fSjeremylt       }
337885ac19cSjeremylt       case CEED_EVAL_DIV:
338885ac19cSjeremylt         break; // Not implimented
339885ac19cSjeremylt       case CEED_EVAL_CURL:
340885ac19cSjeremylt         break; // Not implimented
341885ac19cSjeremylt       }
342885ac19cSjeremylt     }
343885ac19cSjeremylt   }
344885ac19cSjeremylt 
34542ecf959Sjeremylt   // Zero lvecs
346d1bcdac9Sjeremylt   for (CeedInt i=0; i<numoutputfields; i++) {
347d1bcdac9Sjeremylt     ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr);
348d1bcdac9Sjeremylt     if (vec == CEED_VECTOR_ACTIVE)
349d1bcdac9Sjeremylt       vec = outvec;
350d1bcdac9Sjeremylt     ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr);
35142ecf959Sjeremylt   }
35242ecf959Sjeremylt 
353885ac19cSjeremylt   // Output restriction
3541a4ead9bSjeremylt   for (CeedInt i=0; i<numoutputfields; i++) {
355a2b73c81Sjeremylt     // Restore evec
356a2b73c81Sjeremylt     ierr = CeedVectorRestoreArray(impl->evecs[i+impl->numein],
357d1bcdac9Sjeremylt                                   &impl->edata[i + numinputfields]);
358d1bcdac9Sjeremylt     CeedChk(ierr);
359d1bcdac9Sjeremylt     // Get output vector
360d1bcdac9Sjeremylt     ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); CeedChk(ierr);
361668048e2SJed Brown     // Active
362d1bcdac9Sjeremylt     if (vec == CEED_VECTOR_ACTIVE)
363d1bcdac9Sjeremylt       vec = outvec;
3647ca8db16Sjeremylt     // Restrict
365d1bcdac9Sjeremylt     ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict);
366d1bcdac9Sjeremylt     CeedChk(ierr);
3674dccadb6Sjeremylt     ierr = CeedOperatorFieldGetLMode(opoutputfields[i], &lmode); CeedChk(ierr);
368d1bcdac9Sjeremylt     ierr = CeedElemRestrictionApply(Erestrict, CEED_TRANSPOSE,
369d1bcdac9Sjeremylt                                     lmode, impl->evecs[i+impl->numein], vec,
370668048e2SJed Brown                                     request); CeedChk(ierr);
371885ac19cSjeremylt   }
372885ac19cSjeremylt 
3737ca8db16Sjeremylt   // Restore input arrays
3741a4ead9bSjeremylt   for (CeedInt i=0; i<numinputfields; i++) {
375d1bcdac9Sjeremylt     ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode);
376d1bcdac9Sjeremylt     CeedChk(ierr);
377135a076eSjeremylt     if (emode == CEED_EVAL_WEIGHT) { // Skip
3787ca8db16Sjeremylt     } else {
379a2b73c81Sjeremylt       ierr = CeedVectorRestoreArrayRead(impl->evecs[i],
380d1bcdac9Sjeremylt                                         (const CeedScalar **) &impl->edata[i]);
381d1bcdac9Sjeremylt       CeedChk(ierr);
3827ca8db16Sjeremylt     }
3837ca8db16Sjeremylt   }
3847ca8db16Sjeremylt 
38521617c04Sjeremylt   return 0;
38621617c04Sjeremylt }
38721617c04Sjeremylt 
38821617c04Sjeremylt int CeedOperatorCreate_Ref(CeedOperator op) {
38921617c04Sjeremylt   int ierr;
390fe2413ffSjeremylt   Ceed ceed;
391fe2413ffSjeremylt   ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
3924ce2993fSjeremylt   CeedOperator_Ref *impl;
39321617c04Sjeremylt 
39421617c04Sjeremylt   ierr = CeedCalloc(1, &impl); CeedChk(ierr);
395fe2413ffSjeremylt   ierr = CeedOperatorSetData(op, (void*)&impl);
396fe2413ffSjeremylt 
397fe2413ffSjeremylt   ierr = CeedSetBackendFunction(ceed, "Operator", op, "Apply",
398fe2413ffSjeremylt                                 CeedOperatorApply_Ref); CeedChk(ierr);
399fe2413ffSjeremylt   ierr = CeedSetBackendFunction(ceed, "Operator", op, "Destroy",
400fe2413ffSjeremylt                                 CeedOperatorDestroy_Ref); CeedChk(ierr);
40121617c04Sjeremylt   return 0;
40221617c04Sjeremylt }
403