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 21*885ac19cSjeremylt CeedElemRestriction CEED_RESTRICTION_IDENTITY = NULL; 22*885ac19cSjeremylt CeedBasis CEED_BASIS_COLOCATED = NULL; 23*885ac19cSjeremylt CeedVector CEED_QDATA_NONE = NULL; 24*885ac19cSjeremylt 2521617c04Sjeremylt static int CeedOperatorDestroy_Ref(CeedOperator op) { 2621617c04Sjeremylt CeedOperator_Ref *impl = op->data; 2721617c04Sjeremylt int ierr; 2821617c04Sjeremylt 29*885ac19cSjeremylt for (CeedInt i=0; i<impl->numein+impl->numeout; i++) { 30*885ac19cSjeremylt ierr = CeedVectorDestroy(&impl->evecs[i]); CeedChk(ierr); 31*885ac19cSjeremylt } 32*885ac19cSjeremylt ierr = CeedFree(&impl->evecs); CeedChk(ierr); 33*885ac19cSjeremylt ierr = CeedFree(&impl->edata); CeedChk(ierr); 34*885ac19cSjeremylt 35*885ac19cSjeremylt for (CeedInt i=0; i<impl->numqin+impl->numqout; i++) { 36*885ac19cSjeremylt ierr = CeedFree(&impl->qdata_alloc[i]); CeedChk(ierr); 37*885ac19cSjeremylt } 38*885ac19cSjeremylt ierr = CeedFree(&impl->qdata_alloc); CeedChk(ierr); 39*885ac19cSjeremylt ierr = CeedFree(&impl->qdata); CeedChk(ierr); 40*885ac19cSjeremylt 41*885ac19cSjeremylt ierr = CeedFree(&impl->indata); CeedChk(ierr); 42*885ac19cSjeremylt ierr = CeedFree(&impl->outdata); CeedChk(ierr); 43*885ac19cSjeremylt 4421617c04Sjeremylt ierr = CeedFree(&op->data); CeedChk(ierr); 4521617c04Sjeremylt return 0; 4621617c04Sjeremylt } 4721617c04Sjeremylt 48*885ac19cSjeremylt /* 49*885ac19cSjeremylt Setup infields or outfields 50*885ac19cSjeremylt */ 51*885ac19cSjeremylt static int CeedOperatorSetupFields_Ref(struct CeedQFunctionField qfields[16], 52*885ac19cSjeremylt struct CeedOperatorField ofields[16], 53*885ac19cSjeremylt CeedVector *evecs, CeedScalar **qdata, 54*885ac19cSjeremylt CeedScalar **qdata_alloc, CeedScalar **indata, 55*885ac19cSjeremylt CeedInt starti, CeedInt starte, 56*885ac19cSjeremylt CeedInt startq, CeedInt numfields, CeedInt Q) { 57*885ac19cSjeremylt CeedInt dim, ierr, ie=starte, iq=startq, ncomp; 5821617c04Sjeremylt 59*885ac19cSjeremylt // Loop over fields 60*885ac19cSjeremylt for (CeedInt i=0; i<numfields; i++) { 61*885ac19cSjeremylt if (ofields[i].Erestrict) { 62*885ac19cSjeremylt ierr = CeedElemRestrictionCreateVector(ofields[i].Erestrict, NULL, &evecs[ie]); 6321617c04Sjeremylt CeedChk(ierr); 64*885ac19cSjeremylt ie++; 6521617c04Sjeremylt } 66*885ac19cSjeremylt CeedEvalMode emode = qfields[i].emode; 67*885ac19cSjeremylt switch(emode) { 68*885ac19cSjeremylt case CEED_EVAL_NONE: 69*885ac19cSjeremylt break; // No action 70*885ac19cSjeremylt case CEED_EVAL_INTERP: 71*885ac19cSjeremylt ncomp = qfields[i].ncomp; 72*885ac19cSjeremylt ierr = CeedMalloc(Q*ncomp, &qdata_alloc[iq]); CeedChk(ierr); 73*885ac19cSjeremylt qdata[i + starti] = qdata_alloc[iq]; 74*885ac19cSjeremylt iq++; 75*885ac19cSjeremylt break; 76*885ac19cSjeremylt case CEED_EVAL_GRAD: 77*885ac19cSjeremylt ncomp = qfields[i].ncomp; 78*885ac19cSjeremylt dim = ofields[i].basis->dim; 79*885ac19cSjeremylt ierr = CeedMalloc(Q*ncomp*dim, &qdata_alloc[iq]); CeedChk(ierr); 80*885ac19cSjeremylt qdata[i + starti] = qdata_alloc[iq]; 81*885ac19cSjeremylt iq++; 82*885ac19cSjeremylt break; 83*885ac19cSjeremylt case CEED_EVAL_WEIGHT: // Only on input fields 84*885ac19cSjeremylt ierr = CeedMalloc(Q, &qdata_alloc[iq]); CeedChk(ierr); 85*885ac19cSjeremylt ierr = CeedBasisApply(ofields[iq].basis, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 86*885ac19cSjeremylt NULL, qdata_alloc[iq]); CeedChk(ierr); 87*885ac19cSjeremylt qdata[i] = qdata_alloc[iq]; 88*885ac19cSjeremylt indata[i] = qdata[i]; 89*885ac19cSjeremylt iq++; 90*885ac19cSjeremylt break; 91*885ac19cSjeremylt case CEED_EVAL_DIV: 92*885ac19cSjeremylt break; // Not implimented 93*885ac19cSjeremylt case CEED_EVAL_CURL: 94*885ac19cSjeremylt break; // Not implimented 9521617c04Sjeremylt } 96*885ac19cSjeremylt } 9721617c04Sjeremylt return 0; 9821617c04Sjeremylt } 9921617c04Sjeremylt 100*885ac19cSjeremylt /* 101*885ac19cSjeremylt CeedOperator needs to connect all the named fields (be they active or passive) 102*885ac19cSjeremylt to the named inputs and outputs of its CeedQFunction. 103*885ac19cSjeremylt */ 104*885ac19cSjeremylt static int CeedOperatorSetup_Ref(CeedOperator op) { 105*885ac19cSjeremylt if (op->setupdone) return 0; 106*885ac19cSjeremylt CeedOperator_Ref *opref = op->data; 107*885ac19cSjeremylt CeedQFunction qf = op->qf; 108*885ac19cSjeremylt CeedInt Q = op->numqpoints; 10921617c04Sjeremylt int ierr; 11021617c04Sjeremylt 111*885ac19cSjeremylt // Count infield and outfield array sizes and evectors 112*885ac19cSjeremylt for (CeedInt i=0; i<qf->numinputfields; i++) { 113*885ac19cSjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 114*885ac19cSjeremylt opref->numqin += !!(emode & CEED_EVAL_INTERP) + !!(emode & CEED_EVAL_GRAD) + !! 115*885ac19cSjeremylt (emode & CEED_EVAL_WEIGHT); 116*885ac19cSjeremylt opref->numein += 117*885ac19cSjeremylt !!op->inputfields[i].Erestrict; // Need E-vector when restriction exists 11821617c04Sjeremylt } 119*885ac19cSjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 120*885ac19cSjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 121*885ac19cSjeremylt opref->numqout += !!(emode & CEED_EVAL_INTERP) + !!(emode & CEED_EVAL_GRAD); 122*885ac19cSjeremylt opref->numeout += !!op->outputfields[i].Erestrict; 123*885ac19cSjeremylt } 124*885ac19cSjeremylt 125*885ac19cSjeremylt // Allocate 126*885ac19cSjeremylt ierr = CeedCalloc(opref->numein + opref->numeout, &opref->evecs); CeedChk(ierr); 127*885ac19cSjeremylt ierr = CeedCalloc(qf->numinputfields + qf->numoutputfields, &opref->edata); 128*885ac19cSjeremylt CeedChk(ierr); 129*885ac19cSjeremylt 130*885ac19cSjeremylt ierr = CeedCalloc(opref->numqin + opref->numqout, &opref->qdata_alloc); 131*885ac19cSjeremylt CeedChk(ierr); 132*885ac19cSjeremylt ierr = CeedCalloc(qf->numinputfields + qf->numoutputfields, &opref->qdata); 133*885ac19cSjeremylt CeedChk(ierr); 134*885ac19cSjeremylt 135*885ac19cSjeremylt ierr = CeedCalloc(16, &opref->indata); CeedChk(ierr); 136*885ac19cSjeremylt ierr = CeedCalloc(16, &opref->outdata); CeedChk(ierr); 137*885ac19cSjeremylt 138*885ac19cSjeremylt // Set up infield and outfield pointer arrays 139*885ac19cSjeremylt // Infields 140*885ac19cSjeremylt ierr = CeedOperatorSetupFields_Ref(qf->inputfields, op->inputfields, 141*885ac19cSjeremylt opref->evecs, opref->qdata, opref->qdata_alloc, 142*885ac19cSjeremylt opref->indata, 0, 0, 0, 143*885ac19cSjeremylt qf->numinputfields, Q); CeedChk(ierr); 144*885ac19cSjeremylt 145*885ac19cSjeremylt // Outfields 146*885ac19cSjeremylt ierr = CeedOperatorSetupFields_Ref(qf->outputfields, op->outputfields, 147*885ac19cSjeremylt opref->evecs, opref->qdata, opref->qdata_alloc, 148*885ac19cSjeremylt opref->indata, qf->numinputfields, opref->numein, 149*885ac19cSjeremylt opref->numqin, qf->numoutputfields, Q); CeedChk(ierr); 150*885ac19cSjeremylt 151*885ac19cSjeremylt op->setupdone = 1; 152*885ac19cSjeremylt 153*885ac19cSjeremylt return 0; 154*885ac19cSjeremylt } 155*885ac19cSjeremylt 156*885ac19cSjeremylt static int CeedOperatorApply_Ref(CeedOperator op, CeedVector invec, 157*885ac19cSjeremylt CeedVector outvec, CeedRequest *request) { 158*885ac19cSjeremylt CeedOperator_Ref *opref = op->data; 159*885ac19cSjeremylt CeedInt Q = op->numqpoints, elemsize; 160*885ac19cSjeremylt int ierr; 161*885ac19cSjeremylt CeedQFunction qf = op->qf; 162*885ac19cSjeremylt CeedTransposeMode lmode = CEED_NOTRANSPOSE; 163*885ac19cSjeremylt 164*885ac19cSjeremylt // Setup 165*885ac19cSjeremylt ierr = CeedOperatorSetup_Ref(op); CeedChk(ierr); 166*885ac19cSjeremylt 167*885ac19cSjeremylt // Input Evecs and Restriction 168*885ac19cSjeremylt for (CeedInt i=0,iein=0; i<qf->numinputfields; i++) { 169*885ac19cSjeremylt // Restriction 170*885ac19cSjeremylt if (op->inputfields[i].Erestrict) { 171*885ac19cSjeremylt // Passive 172*885ac19cSjeremylt if (op->inputfields[i].vec) { 173*885ac19cSjeremylt ierr = CeedElemRestrictionApply(op->inputfields[i].Erestrict, CEED_NOTRANSPOSE, 174*885ac19cSjeremylt lmode, op->inputfields[i].vec, opref->evecs[iein], 175*885ac19cSjeremylt request); CeedChk(ierr); 176*885ac19cSjeremylt ierr = CeedVectorGetArrayRead(opref->evecs[iein], CEED_MEM_HOST, 177*885ac19cSjeremylt (const CeedScalar **) &opref->edata[i]); CeedChk(ierr); 178*885ac19cSjeremylt iein++; 179*885ac19cSjeremylt } else { 180*885ac19cSjeremylt // Active 181*885ac19cSjeremylt ierr = CeedElemRestrictionApply(op->inputfields[i].Erestrict, CEED_NOTRANSPOSE, 182*885ac19cSjeremylt lmode, invec, opref->evecs[iein], request); CeedChk(ierr); 183*885ac19cSjeremylt ierr = CeedVectorGetArrayRead(opref->evecs[iein], CEED_MEM_HOST, 184*885ac19cSjeremylt (const CeedScalar **) &opref->edata[i]); CeedChk(ierr); 185*885ac19cSjeremylt iein++; 186*885ac19cSjeremylt } 187*885ac19cSjeremylt } else { 188*885ac19cSjeremylt // No restriction 189*885ac19cSjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 190*885ac19cSjeremylt if (emode & CEED_EVAL_WEIGHT) { 191*885ac19cSjeremylt } else { 192*885ac19cSjeremylt ierr = CeedVectorGetArrayRead(op->inputfields[i].vec, CEED_MEM_HOST, 193*885ac19cSjeremylt (const CeedScalar **) &opref->edata[i]); CeedChk(ierr); 194*885ac19cSjeremylt } 195*885ac19cSjeremylt } 196*885ac19cSjeremylt } 197*885ac19cSjeremylt 198*885ac19cSjeremylt // Output Evecs 199*885ac19cSjeremylt for (CeedInt i=0,ieout=opref->numein; i<qf->numoutputfields; i++) { 200*885ac19cSjeremylt // Restriction 201*885ac19cSjeremylt if (op->outputfields[i].Erestrict) { 202*885ac19cSjeremylt ierr = CeedVectorGetArray(opref->evecs[ieout], CEED_MEM_HOST, 203*885ac19cSjeremylt &opref->edata[i + qf->numinputfields]); CeedChk(ierr); 204*885ac19cSjeremylt ieout++; 205*885ac19cSjeremylt } else { 206*885ac19cSjeremylt // No restriction 207*885ac19cSjeremylt // Passive 208*885ac19cSjeremylt if (op->inputfields[i].vec) { 209*885ac19cSjeremylt ierr = CeedVectorGetArray(op->inputfields[i].vec, CEED_MEM_HOST, 210*885ac19cSjeremylt &opref->edata[i + qf->numinputfields]); CeedChk(ierr); 211*885ac19cSjeremylt } else { 212*885ac19cSjeremylt // Active 213*885ac19cSjeremylt ierr = CeedVectorGetArray(outvec, CEED_MEM_HOST, 214*885ac19cSjeremylt &opref->edata[i + qf->numinputfields]); CeedChk(ierr); 215*885ac19cSjeremylt } 216*885ac19cSjeremylt } 217*885ac19cSjeremylt } 218*885ac19cSjeremylt 219*885ac19cSjeremylt // Output Qvecs 220*885ac19cSjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 221*885ac19cSjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 222*885ac19cSjeremylt if (emode != CEED_EVAL_NONE) { 223*885ac19cSjeremylt opref->outdata[i] = opref->qdata[i + qf->numinputfields]; 224*885ac19cSjeremylt } 225*885ac19cSjeremylt } 226*885ac19cSjeremylt 227*885ac19cSjeremylt // Loop through elements 228*885ac19cSjeremylt for (CeedInt e=0; e<op->numelements; e++) { 229*885ac19cSjeremylt // Input basis apply if needed 230*885ac19cSjeremylt for (CeedInt i=0; i<qf->numinputfields; i++) { 231*885ac19cSjeremylt // Get elemsize 232*885ac19cSjeremylt if (op->inputfields[i].Erestrict) { 233*885ac19cSjeremylt elemsize = op->inputfields[i].Erestrict->elemsize; 234*885ac19cSjeremylt } else { 235*885ac19cSjeremylt elemsize = Q; 236*885ac19cSjeremylt } 237*885ac19cSjeremylt // Get emode, ncomp 238*885ac19cSjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 239*885ac19cSjeremylt CeedInt ncomp = qf->inputfields[i].ncomp; 240*885ac19cSjeremylt // Basis action 241*885ac19cSjeremylt switch(emode) { 242*885ac19cSjeremylt case CEED_EVAL_NONE: 243*885ac19cSjeremylt opref->indata[i] = &opref->edata[i][e*Q*ncomp]; 244*885ac19cSjeremylt break; 245*885ac19cSjeremylt case CEED_EVAL_INTERP: 246*885ac19cSjeremylt ierr = CeedBasisApply(op->inputfields[i].basis, CEED_NOTRANSPOSE, 247*885ac19cSjeremylt CEED_EVAL_INTERP, &opref->edata[i][e*elemsize*ncomp], opref->qdata[i]); 248*885ac19cSjeremylt CeedChk(ierr); 249*885ac19cSjeremylt opref->indata[i] = opref->qdata[i]; 250*885ac19cSjeremylt break; 251*885ac19cSjeremylt case CEED_EVAL_GRAD: 252*885ac19cSjeremylt ierr = CeedBasisApply(op->inputfields[i].basis, CEED_NOTRANSPOSE, 253*885ac19cSjeremylt CEED_EVAL_GRAD, &opref->edata[i][e*elemsize*ncomp], opref->qdata[i]); 254*885ac19cSjeremylt CeedChk(ierr); 255*885ac19cSjeremylt opref->indata[i] = opref->qdata[i]; 256*885ac19cSjeremylt break; 257*885ac19cSjeremylt case CEED_EVAL_WEIGHT: 258*885ac19cSjeremylt break; // No action 259*885ac19cSjeremylt case CEED_EVAL_DIV: 260*885ac19cSjeremylt break; // Not implimented 261*885ac19cSjeremylt case CEED_EVAL_CURL: 262*885ac19cSjeremylt break; // Not implimented 263*885ac19cSjeremylt } 264*885ac19cSjeremylt } 265*885ac19cSjeremylt // Output pointers 266*885ac19cSjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 267*885ac19cSjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 268*885ac19cSjeremylt if (emode == CEED_EVAL_NONE) { 269*885ac19cSjeremylt CeedInt ncomp = qf->outputfields[i].ncomp; 270*885ac19cSjeremylt opref->outdata[i] = &opref->edata[i + qf->numinputfields][e*Q*ncomp]; 271*885ac19cSjeremylt } 272*885ac19cSjeremylt } 273*885ac19cSjeremylt // Q function 274*885ac19cSjeremylt ierr = CeedQFunctionApply(op->qf, Q, (const CeedScalar * const*) opref->indata, 275*885ac19cSjeremylt opref->outdata); CeedChk(ierr); 276*885ac19cSjeremylt 277*885ac19cSjeremylt // Output basis apply if needed 278*885ac19cSjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 279*885ac19cSjeremylt // Get elemsize 280*885ac19cSjeremylt if (op->outputfields[i].Erestrict) { 281*885ac19cSjeremylt elemsize = op->outputfields[i].Erestrict->elemsize; 282*885ac19cSjeremylt } else { 283*885ac19cSjeremylt elemsize = Q; 284*885ac19cSjeremylt } 285*885ac19cSjeremylt // Get emode, ncomp 286*885ac19cSjeremylt CeedInt ncomp = qf->outputfields[i].ncomp; 287*885ac19cSjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 288*885ac19cSjeremylt // Basis action 289*885ac19cSjeremylt switch(emode) { 290*885ac19cSjeremylt case CEED_EVAL_NONE: 291*885ac19cSjeremylt break; // No action 292*885ac19cSjeremylt case CEED_EVAL_INTERP: 293*885ac19cSjeremylt ierr = CeedBasisApply(op->outputfields[i].basis, CEED_TRANSPOSE, 294*885ac19cSjeremylt CEED_EVAL_INTERP, opref->outdata[i], 295*885ac19cSjeremylt &opref->edata[i + qf->numinputfields][e*elemsize*ncomp]); CeedChk(ierr); 296*885ac19cSjeremylt break; 297*885ac19cSjeremylt case CEED_EVAL_GRAD: 298*885ac19cSjeremylt ierr = CeedBasisApply(op->outputfields[i].basis, CEED_TRANSPOSE, CEED_EVAL_GRAD, 299*885ac19cSjeremylt opref->outdata[i], &opref->edata[i + qf->numinputfields][e*elemsize*ncomp]); 300*885ac19cSjeremylt CeedChk(ierr); 301*885ac19cSjeremylt break; 302*885ac19cSjeremylt case CEED_EVAL_WEIGHT: 303*885ac19cSjeremylt break; // Should not occur 304*885ac19cSjeremylt case CEED_EVAL_DIV: 305*885ac19cSjeremylt break; // Not implimented 306*885ac19cSjeremylt case CEED_EVAL_CURL: 307*885ac19cSjeremylt break; // Not implimented 308*885ac19cSjeremylt } 309*885ac19cSjeremylt } 310*885ac19cSjeremylt } 311*885ac19cSjeremylt 312*885ac19cSjeremylt // Output restriction 313*885ac19cSjeremylt for (CeedInt i=0,ieout=opref->numein; i<qf->numoutputfields; i++) { 314*885ac19cSjeremylt // Restriction 315*885ac19cSjeremylt if (op->outputfields[i].Erestrict) { 316*885ac19cSjeremylt // Passive 317*885ac19cSjeremylt if (op->outputfields[i].vec) { 318*885ac19cSjeremylt ierr = CeedVectorRestoreArray(opref->evecs[ieout], 319*885ac19cSjeremylt &opref->edata[i + qf->numinputfields]); CeedChk(ierr); 320*885ac19cSjeremylt ierr = CeedElemRestrictionApply(op->outputfields[i].Erestrict, CEED_TRANSPOSE, 321*885ac19cSjeremylt lmode, opref->evecs[ieout], op->outputfields[i].vec, request); CeedChk(ierr); 322*885ac19cSjeremylt ieout++; 323*885ac19cSjeremylt } else { 324*885ac19cSjeremylt // Active 325*885ac19cSjeremylt ierr = CeedVectorRestoreArray(opref->evecs[ieout], 326*885ac19cSjeremylt &opref->edata[i + qf->numinputfields]); CeedChk(ierr); 327*885ac19cSjeremylt ierr = CeedElemRestrictionApply(op->outputfields[i].Erestrict, CEED_TRANSPOSE, 328*885ac19cSjeremylt lmode, opref->evecs[ieout], outvec, request); CeedChk(ierr); 329*885ac19cSjeremylt ieout++; 330*885ac19cSjeremylt } 331*885ac19cSjeremylt } else { 332*885ac19cSjeremylt // No Restriction 333*885ac19cSjeremylt // Passive 334*885ac19cSjeremylt if (op->outputfields[i].vec) { 335*885ac19cSjeremylt ierr = CeedVectorRestoreArray(op->outputfields[i].vec, 336*885ac19cSjeremylt &opref->edata[i + qf->numinputfields]); CeedChk(ierr); 337*885ac19cSjeremylt } else { 338*885ac19cSjeremylt // Active 339*885ac19cSjeremylt ierr = CeedVectorRestoreArray(outvec, &opref->edata[i + qf->numinputfields]); 340*885ac19cSjeremylt CeedChk(ierr); 341*885ac19cSjeremylt } 342*885ac19cSjeremylt } 343*885ac19cSjeremylt } 344*885ac19cSjeremylt 34521617c04Sjeremylt return 0; 34621617c04Sjeremylt } 34721617c04Sjeremylt 34821617c04Sjeremylt int CeedOperatorCreate_Ref(CeedOperator op) { 34921617c04Sjeremylt CeedOperator_Ref *impl; 35021617c04Sjeremylt int ierr; 35121617c04Sjeremylt 35221617c04Sjeremylt ierr = CeedCalloc(1, &impl); CeedChk(ierr); 35321617c04Sjeremylt op->data = impl; 35421617c04Sjeremylt op->Destroy = CeedOperatorDestroy_Ref; 35521617c04Sjeremylt op->Apply = CeedOperatorApply_Ref; 35621617c04Sjeremylt return 0; 35721617c04Sjeremylt } 358