121617c04Sjeremylt // Copyright (c) 2017-2018, Lawrence Livermore National Security, LLC. 221617c04Sjeremylt // Produced at the Lawrence Livermore National Laboratory. LLNL-CODE-734707. 321617c04Sjeremylt // All Rights reserved. See files LICENSE and NOTICE for details. 421617c04Sjeremylt // 521617c04Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software 621617c04Sjeremylt // libraries and APIs for efficient high-order finite element and spectral 721617c04Sjeremylt // element discretizations for exascale applications. For more information and 821617c04Sjeremylt // source code availability see http://github.com/ceed. 921617c04Sjeremylt // 1021617c04Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 1121617c04Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office 1221617c04Sjeremylt // of Science and the National Nuclear Security Administration) responsible for 1321617c04Sjeremylt // the planning and preparation of a capable exascale ecosystem, including 1421617c04Sjeremylt // software, applications, hardware, advanced system engineering and early 1521617c04Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative. 1621617c04Sjeremylt 1721617c04Sjeremylt #include <ceed-impl.h> 1821617c04Sjeremylt #include <string.h> 1921617c04Sjeremylt #include "ceed-ref.h" 2021617c04Sjeremylt 2121617c04Sjeremylt static int CeedOperatorDestroy_Ref(CeedOperator op) { 2221617c04Sjeremylt int ierr; 23*4ce2993fSjeremylt CeedOperator_Ref *impl; 24*4ce2993fSjeremylt ierr = CeedOperatorGetData(op, (void*)&impl); CeedChk(ierr); 2521617c04Sjeremylt 26885ac19cSjeremylt for (CeedInt i=0; i<impl->numein+impl->numeout; i++) { 27885ac19cSjeremylt ierr = CeedVectorDestroy(&impl->evecs[i]); CeedChk(ierr); 28885ac19cSjeremylt } 29885ac19cSjeremylt ierr = CeedFree(&impl->evecs); CeedChk(ierr); 30885ac19cSjeremylt ierr = CeedFree(&impl->edata); CeedChk(ierr); 31885ac19cSjeremylt 32885ac19cSjeremylt for (CeedInt i=0; i<impl->numqin+impl->numqout; i++) { 33885ac19cSjeremylt ierr = CeedFree(&impl->qdata_alloc[i]); CeedChk(ierr); 34885ac19cSjeremylt } 35885ac19cSjeremylt ierr = CeedFree(&impl->qdata_alloc); CeedChk(ierr); 36885ac19cSjeremylt ierr = CeedFree(&impl->qdata); CeedChk(ierr); 37885ac19cSjeremylt 38885ac19cSjeremylt ierr = CeedFree(&impl->indata); CeedChk(ierr); 39885ac19cSjeremylt ierr = CeedFree(&impl->outdata); CeedChk(ierr); 40885ac19cSjeremylt 4121617c04Sjeremylt ierr = CeedFree(&op->data); CeedChk(ierr); 4221617c04Sjeremylt return 0; 4321617c04Sjeremylt } 4421617c04Sjeremylt 45885ac19cSjeremylt /* 46885ac19cSjeremylt Setup infields or outfields 47885ac19cSjeremylt */ 48885ac19cSjeremylt static int CeedOperatorSetupFields_Ref(struct CeedQFunctionField qfields[16], 49885ac19cSjeremylt struct CeedOperatorField ofields[16], 50885ac19cSjeremylt CeedVector *evecs, CeedScalar **qdata, 51885ac19cSjeremylt CeedScalar **qdata_alloc, CeedScalar **indata, 52135a076eSjeremylt CeedInt starti, CeedInt startq, 53135a076eSjeremylt CeedInt numfields, CeedInt Q) { 54135a076eSjeremylt CeedInt dim, ierr, iq=startq, ncomp; 5521617c04Sjeremylt 56885ac19cSjeremylt // Loop over fields 57885ac19cSjeremylt for (CeedInt i=0; i<numfields; i++) { 58885ac19cSjeremylt CeedEvalMode emode = qfields[i].emode; 59135a076eSjeremylt 60135a076eSjeremylt if (emode != CEED_EVAL_WEIGHT) { 614b8bea3bSJed Brown ierr = CeedElemRestrictionCreateVector(ofields[i].Erestrict, NULL, 624b8bea3bSJed Brown &evecs[i+starti]); 63135a076eSjeremylt CeedChk(ierr); 64135a076eSjeremylt } 65135a076eSjeremylt 66885ac19cSjeremylt switch(emode) { 67885ac19cSjeremylt case CEED_EVAL_NONE: 68885ac19cSjeremylt break; // No action 69885ac19cSjeremylt case CEED_EVAL_INTERP: 70885ac19cSjeremylt ncomp = qfields[i].ncomp; 71885ac19cSjeremylt ierr = CeedMalloc(Q*ncomp, &qdata_alloc[iq]); CeedChk(ierr); 72885ac19cSjeremylt qdata[i + starti] = qdata_alloc[iq]; 73885ac19cSjeremylt iq++; 74885ac19cSjeremylt break; 75885ac19cSjeremylt case CEED_EVAL_GRAD: 76885ac19cSjeremylt ncomp = qfields[i].ncomp; 77*4ce2993fSjeremylt ierr = CeedBasisGetDimension(ofields[i].basis, &dim); CeedChk(ierr); 78885ac19cSjeremylt ierr = CeedMalloc(Q*ncomp*dim, &qdata_alloc[iq]); CeedChk(ierr); 79885ac19cSjeremylt qdata[i + starti] = qdata_alloc[iq]; 80885ac19cSjeremylt iq++; 81885ac19cSjeremylt break; 82885ac19cSjeremylt case CEED_EVAL_WEIGHT: // Only on input fields 83885ac19cSjeremylt ierr = CeedMalloc(Q, &qdata_alloc[iq]); CeedChk(ierr); 84d3181881Sjeremylt ierr = CeedBasisApply(ofields[iq].basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 85885ac19cSjeremylt NULL, qdata_alloc[iq]); CeedChk(ierr); 86885ac19cSjeremylt qdata[i] = qdata_alloc[iq]; 87885ac19cSjeremylt indata[i] = qdata[i]; 88885ac19cSjeremylt iq++; 89885ac19cSjeremylt break; 90885ac19cSjeremylt case CEED_EVAL_DIV: 91885ac19cSjeremylt break; // Not implimented 92885ac19cSjeremylt case CEED_EVAL_CURL: 93885ac19cSjeremylt break; // Not implimented 9421617c04Sjeremylt } 95885ac19cSjeremylt } 9621617c04Sjeremylt return 0; 9721617c04Sjeremylt } 9821617c04Sjeremylt 99885ac19cSjeremylt /* 100885ac19cSjeremylt CeedOperator needs to connect all the named fields (be they active or passive) 101885ac19cSjeremylt to the named inputs and outputs of its CeedQFunction. 102885ac19cSjeremylt */ 103885ac19cSjeremylt static int CeedOperatorSetup_Ref(CeedOperator op) { 10421617c04Sjeremylt int ierr; 105*4ce2993fSjeremylt bool setupdone; 106*4ce2993fSjeremylt ierr = CeedOperatorGetSetupStatus(op, &setupdone); CeedChk(ierr); 107*4ce2993fSjeremylt if (setupdone) return 0; 108*4ce2993fSjeremylt CeedOperator_Ref *impl; 109*4ce2993fSjeremylt ierr = CeedOperatorGetData(op, (void*)&impl); CeedChk(ierr); 110*4ce2993fSjeremylt CeedQFunction qf; 111*4ce2993fSjeremylt ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 112*4ce2993fSjeremylt CeedInt Q, numinputfields, numoutputfields; 113*4ce2993fSjeremylt ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 114a8de75f0Sjeremylt ierr = CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 115a8de75f0Sjeremylt CeedChk(ierr); 116*4ce2993fSjeremylt 117*4ce2993fSjeremylt // Count infield and outfield array sizes and evectors 1181a4ead9bSjeremylt impl->numein = numinputfields; 1191a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 120885ac19cSjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 1218d94b059Sjeremylt impl->numqin += !!(emode & CEED_EVAL_INTERP) + !!(emode & CEED_EVAL_GRAD) + 1228d94b059Sjeremylt !!(emode & CEED_EVAL_WEIGHT); 12321617c04Sjeremylt } 1241a4ead9bSjeremylt impl->numeout = numoutputfields; 1251a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 126885ac19cSjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 127a2b73c81Sjeremylt impl->numqout += !!(emode & CEED_EVAL_INTERP) + !!(emode & CEED_EVAL_GRAD); 128885ac19cSjeremylt } 129885ac19cSjeremylt 130885ac19cSjeremylt // Allocate 131a2b73c81Sjeremylt ierr = CeedCalloc(impl->numein + impl->numeout, &impl->evecs); CeedChk(ierr); 132a2b73c81Sjeremylt ierr = CeedCalloc(impl->numein + impl->numeout, &impl->edata); 133885ac19cSjeremylt CeedChk(ierr); 134885ac19cSjeremylt 135a2b73c81Sjeremylt ierr = CeedCalloc(impl->numqin + impl->numqout, &impl->qdata_alloc); 136885ac19cSjeremylt CeedChk(ierr); 1371a4ead9bSjeremylt ierr = CeedCalloc(numinputfields + numoutputfields, &impl->qdata); 138885ac19cSjeremylt CeedChk(ierr); 139885ac19cSjeremylt 140a2b73c81Sjeremylt ierr = CeedCalloc(16, &impl->indata); CeedChk(ierr); 141a2b73c81Sjeremylt ierr = CeedCalloc(16, &impl->outdata); CeedChk(ierr); 142885ac19cSjeremylt 143885ac19cSjeremylt // Set up infield and outfield pointer arrays 144885ac19cSjeremylt // Infields 145885ac19cSjeremylt ierr = CeedOperatorSetupFields_Ref(qf->inputfields, op->inputfields, 146a2b73c81Sjeremylt impl->evecs, impl->qdata, impl->qdata_alloc, 147a2b73c81Sjeremylt impl->indata, 0, 0, 1481a4ead9bSjeremylt numinputfields, Q); CeedChk(ierr); 149885ac19cSjeremylt 150885ac19cSjeremylt // Outfields 151885ac19cSjeremylt ierr = CeedOperatorSetupFields_Ref(qf->outputfields, op->outputfields, 152a2b73c81Sjeremylt impl->evecs, impl->qdata, impl->qdata_alloc, 1531a4ead9bSjeremylt impl->indata, numinputfields, 1541a4ead9bSjeremylt impl->numqin, numoutputfields, Q); CeedChk(ierr); 155885ac19cSjeremylt 1568d94b059Sjeremylt // Input Qvecs 1571a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 1588d94b059Sjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 1598d94b059Sjeremylt if ((emode != CEED_EVAL_NONE) && (emode != CEED_EVAL_WEIGHT)) 1608d94b059Sjeremylt impl->indata[i] = impl->qdata[i]; 1618d94b059Sjeremylt } 1627ca8db16Sjeremylt // Output Qvecs 1631a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 1647ca8db16Sjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 1658d94b059Sjeremylt if (emode != CEED_EVAL_NONE) 1661a4ead9bSjeremylt impl->outdata[i] = impl->qdata[i + numinputfields]; 1677ca8db16Sjeremylt } 1687ca8db16Sjeremylt 169*4ce2993fSjeremylt 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; 177*4ce2993fSjeremylt CeedOperator_Ref *impl; 178*4ce2993fSjeremylt ierr = CeedOperatorGetData(op, (void*)&impl); CeedChk(ierr); 179*4ce2993fSjeremylt CeedQFunction qf; 180*4ce2993fSjeremylt ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 181*4ce2993fSjeremylt CeedInt Q, numelements, elemsize, numinputfields, numoutputfields; 182*4ce2993fSjeremylt ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChk(ierr); 183*4ce2993fSjeremylt ierr = CeedOperatorGetNumElements(op, &numelements); CeedChk(ierr); 184*4ce2993fSjeremylt ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 185*4ce2993fSjeremylt CeedChk(ierr); 186885ac19cSjeremylt CeedTransposeMode lmode = CEED_NOTRANSPOSE; 187885ac19cSjeremylt 188885ac19cSjeremylt // Setup 189885ac19cSjeremylt ierr = CeedOperatorSetup_Ref(op); CeedChk(ierr); 190885ac19cSjeremylt 191885ac19cSjeremylt // Input Evecs and Restriction 1921a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 193668048e2SJed Brown CeedEvalMode emode = qf->inputfields[i].emode; 194135a076eSjeremylt if (emode == CEED_EVAL_WEIGHT) { // Skip 195668048e2SJed Brown } else { 196668048e2SJed Brown // Active 197668048e2SJed Brown if (op->inputfields[i].vec == CEED_VECTOR_ACTIVE) { 198668048e2SJed Brown // Restrict 199668048e2SJed Brown ierr = CeedElemRestrictionApply(op->inputfields[i].Erestrict, CEED_NOTRANSPOSE, 200a2b73c81Sjeremylt lmode, invec, impl->evecs[i], 201668048e2SJed Brown request); CeedChk(ierr); 202668048e2SJed Brown // Get evec 203a2b73c81Sjeremylt ierr = CeedVectorGetArrayRead(impl->evecs[i], CEED_MEM_HOST, 204a2b73c81Sjeremylt (const CeedScalar **) &impl->edata[i]); CeedChk(ierr); 205668048e2SJed Brown } else { 206885ac19cSjeremylt // Passive 2077ca8db16Sjeremylt // Restrict 208885ac19cSjeremylt ierr = CeedElemRestrictionApply(op->inputfields[i].Erestrict, CEED_NOTRANSPOSE, 209a2b73c81Sjeremylt lmode, op->inputfields[i].vec, impl->evecs[i], 210885ac19cSjeremylt request); CeedChk(ierr); 2117ca8db16Sjeremylt // Get evec 212a2b73c81Sjeremylt ierr = CeedVectorGetArrayRead(impl->evecs[i], CEED_MEM_HOST, 213a2b73c81Sjeremylt (const CeedScalar **) &impl->edata[i]); CeedChk(ierr); 214885ac19cSjeremylt } 215885ac19cSjeremylt } 216885ac19cSjeremylt } 217885ac19cSjeremylt 218885ac19cSjeremylt // Output Evecs 2191a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 220a2b73c81Sjeremylt ierr = CeedVectorGetArray(impl->evecs[i+impl->numein], CEED_MEM_HOST, 2211a4ead9bSjeremylt &impl->edata[i + numinputfields]); CeedChk(ierr); 222885ac19cSjeremylt } 223885ac19cSjeremylt 224885ac19cSjeremylt // Loop through elements 225*4ce2993fSjeremylt for (CeedInt e=0; e<numelements; e++) { 226885ac19cSjeremylt // Input basis apply if needed 2271a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 228135a076eSjeremylt // Get elemsize, emode, ncomp 229*4ce2993fSjeremylt ierr = CeedElemRestrictionGetElementSize( 230*4ce2993fSjeremylt op->inputfields[i].Erestrict, &elemsize); CeedChk(ierr); 231885ac19cSjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 232885ac19cSjeremylt CeedInt ncomp = qf->inputfields[i].ncomp; 233885ac19cSjeremylt // Basis action 234885ac19cSjeremylt switch(emode) { 235885ac19cSjeremylt case CEED_EVAL_NONE: 236a2b73c81Sjeremylt impl->indata[i] = &impl->edata[i][e*Q*ncomp]; 237885ac19cSjeremylt break; 238885ac19cSjeremylt case CEED_EVAL_INTERP: 239d3181881Sjeremylt ierr = CeedBasisApply(op->inputfields[i].basis, 1, CEED_NOTRANSPOSE, 240a2b73c81Sjeremylt CEED_EVAL_INTERP, &impl->edata[i][e*elemsize*ncomp], impl->qdata[i]); 241885ac19cSjeremylt CeedChk(ierr); 242885ac19cSjeremylt break; 243885ac19cSjeremylt case CEED_EVAL_GRAD: 244d3181881Sjeremylt ierr = CeedBasisApply(op->inputfields[i].basis, 1, CEED_NOTRANSPOSE, 245a2b73c81Sjeremylt CEED_EVAL_GRAD, &impl->edata[i][e*elemsize*ncomp], impl->qdata[i]); 246885ac19cSjeremylt CeedChk(ierr); 247885ac19cSjeremylt break; 248885ac19cSjeremylt case CEED_EVAL_WEIGHT: 249885ac19cSjeremylt break; // No action 250885ac19cSjeremylt case CEED_EVAL_DIV: 251885ac19cSjeremylt break; // Not implimented 252885ac19cSjeremylt case CEED_EVAL_CURL: 253885ac19cSjeremylt break; // Not implimented 254885ac19cSjeremylt } 255885ac19cSjeremylt } 256885ac19cSjeremylt // Output pointers 2571a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 258885ac19cSjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 259885ac19cSjeremylt if (emode == CEED_EVAL_NONE) { 260885ac19cSjeremylt CeedInt ncomp = qf->outputfields[i].ncomp; 2611a4ead9bSjeremylt impl->outdata[i] = &impl->edata[i + numinputfields][e*Q*ncomp]; 262885ac19cSjeremylt } 263885ac19cSjeremylt } 264885ac19cSjeremylt // Q function 265*4ce2993fSjeremylt ierr = CeedQFunctionApply(qf, Q, (const CeedScalar * const*) impl->indata, 266a2b73c81Sjeremylt impl->outdata); CeedChk(ierr); 267885ac19cSjeremylt 268885ac19cSjeremylt // Output basis apply if needed 2691a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 270135a076eSjeremylt // Get elemsize, emode, ncomp 271*4ce2993fSjeremylt ierr = CeedElemRestrictionGetElementSize( 272*4ce2993fSjeremylt op->outputfields[i].Erestrict, &elemsize); CeedChk(ierr); 273885ac19cSjeremylt CeedInt ncomp = qf->outputfields[i].ncomp; 274885ac19cSjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 275885ac19cSjeremylt // Basis action 276885ac19cSjeremylt switch(emode) { 277885ac19cSjeremylt case CEED_EVAL_NONE: 278885ac19cSjeremylt break; // No action 279885ac19cSjeremylt case CEED_EVAL_INTERP: 280d3181881Sjeremylt ierr = CeedBasisApply(op->outputfields[i].basis, 1, CEED_TRANSPOSE, 281a2b73c81Sjeremylt CEED_EVAL_INTERP, impl->outdata[i], 2821a4ead9bSjeremylt &impl->edata[i + numinputfields][e*elemsize*ncomp]); 2838d94b059Sjeremylt CeedChk(ierr); 284885ac19cSjeremylt break; 285885ac19cSjeremylt case CEED_EVAL_GRAD: 2860c7a96bbSjeremylt ierr = CeedBasisApply(op->outputfields[i].basis, 1, CEED_TRANSPOSE, 2870c7a96bbSjeremylt CEED_EVAL_GRAD, 2881a4ead9bSjeremylt impl->outdata[i], &impl->edata[i + numinputfields][e*elemsize*ncomp]); 289885ac19cSjeremylt CeedChk(ierr); 290885ac19cSjeremylt break; 291*4ce2993fSjeremylt case CEED_EVAL_WEIGHT: { 292*4ce2993fSjeremylt Ceed ceed; 293*4ce2993fSjeremylt ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 294*4ce2993fSjeremylt return CeedError(ceed, 1, 2958d94b059Sjeremylt "CEED_EVAL_WEIGHT cannot be an output evaluation mode"); 296885ac19cSjeremylt break; // Should not occur 297*4ce2993fSjeremylt } 298885ac19cSjeremylt case CEED_EVAL_DIV: 299885ac19cSjeremylt break; // Not implimented 300885ac19cSjeremylt case CEED_EVAL_CURL: 301885ac19cSjeremylt break; // Not implimented 302885ac19cSjeremylt } 303885ac19cSjeremylt } 304885ac19cSjeremylt } 305885ac19cSjeremylt 30642ecf959Sjeremylt // Zero lvecs 30742ecf959Sjeremylt ierr = CeedVectorSetValue(outvec, 0.0); CeedChk(ierr); 308*4ce2993fSjeremylt for (CeedInt i=0; i<numoutputfields; i++) 30942ecf959Sjeremylt if (op->outputfields[i].vec != CEED_VECTOR_ACTIVE) { 31042ecf959Sjeremylt ierr = CeedVectorSetValue(op->outputfields[i].vec, 0.0); CeedChk(ierr); 31142ecf959Sjeremylt } 31242ecf959Sjeremylt 313885ac19cSjeremylt // Output restriction 3141a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 315a2b73c81Sjeremylt // Restore evec 316a2b73c81Sjeremylt ierr = CeedVectorRestoreArray(impl->evecs[i+impl->numein], 3171a4ead9bSjeremylt &impl->edata[i + numinputfields]); CeedChk(ierr); 318668048e2SJed Brown // Active 319668048e2SJed Brown if (op->outputfields[i].vec == CEED_VECTOR_ACTIVE) { 3207ca8db16Sjeremylt // Restrict 321885ac19cSjeremylt ierr = CeedElemRestrictionApply(op->outputfields[i].Erestrict, CEED_TRANSPOSE, 322a2b73c81Sjeremylt lmode, impl->evecs[i+impl->numein], outvec, request); CeedChk(ierr); 323885ac19cSjeremylt } else { 324885ac19cSjeremylt // Passive 325668048e2SJed Brown // Restrict 326668048e2SJed Brown ierr = CeedElemRestrictionApply(op->outputfields[i].Erestrict, CEED_TRANSPOSE, 327a2b73c81Sjeremylt lmode, impl->evecs[i+impl->numein], op->outputfields[i].vec, 328668048e2SJed Brown request); CeedChk(ierr); 329885ac19cSjeremylt } 330885ac19cSjeremylt } 331885ac19cSjeremylt 3327ca8db16Sjeremylt // Restore input arrays 3331a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 3347ca8db16Sjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 335135a076eSjeremylt if (emode == CEED_EVAL_WEIGHT) { // Skip 3367ca8db16Sjeremylt } else { 337a2b73c81Sjeremylt ierr = CeedVectorRestoreArrayRead(impl->evecs[i], 338a2b73c81Sjeremylt (const CeedScalar **) &impl->edata[i]); CeedChk(ierr); 3397ca8db16Sjeremylt } 3407ca8db16Sjeremylt } 3417ca8db16Sjeremylt 34221617c04Sjeremylt return 0; 34321617c04Sjeremylt } 34421617c04Sjeremylt 34521617c04Sjeremylt int CeedOperatorCreate_Ref(CeedOperator op) { 34621617c04Sjeremylt int ierr; 347*4ce2993fSjeremylt CeedOperator_Ref *impl; 34821617c04Sjeremylt 34921617c04Sjeremylt ierr = CeedCalloc(1, &impl); CeedChk(ierr); 35021617c04Sjeremylt op->data = impl; 35121617c04Sjeremylt op->Destroy = CeedOperatorDestroy_Ref; 35221617c04Sjeremylt op->Apply = CeedOperatorApply_Ref; 35321617c04Sjeremylt return 0; 35421617c04Sjeremylt } 355