xref: /libCEED/backends/ref/ceed-ref-operator.c (revision de686571da193802df261a10fbc2ea743b9830da)
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