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 21885ac19cSjeremylt CeedElemRestriction CEED_RESTRICTION_IDENTITY = NULL; 22885ac19cSjeremylt CeedBasis CEED_BASIS_COLOCATED = NULL; 23583b1d4cSjeremylt CeedVector CEED_VECTOR_ACTIVE = NULL; 24583b1d4cSjeremylt CeedVector CEED_VECTOR_NONE = NULL; 25885ac19cSjeremylt 2621617c04Sjeremylt static int CeedOperatorDestroy_Ref(CeedOperator op) { 2721617c04Sjeremylt CeedOperator_Ref *impl = op->data; 2821617c04Sjeremylt int ierr; 2921617c04Sjeremylt 30885ac19cSjeremylt for (CeedInt i=0; i<impl->numein+impl->numeout; i++) { 31885ac19cSjeremylt ierr = CeedVectorDestroy(&impl->evecs[i]); CeedChk(ierr); 32885ac19cSjeremylt } 33885ac19cSjeremylt ierr = CeedFree(&impl->evecs); CeedChk(ierr); 34885ac19cSjeremylt ierr = CeedFree(&impl->edata); CeedChk(ierr); 35885ac19cSjeremylt 36885ac19cSjeremylt for (CeedInt i=0; i<impl->numqin+impl->numqout; i++) { 37885ac19cSjeremylt ierr = CeedFree(&impl->qdata_alloc[i]); CeedChk(ierr); 38885ac19cSjeremylt } 39885ac19cSjeremylt ierr = CeedFree(&impl->qdata_alloc); CeedChk(ierr); 40885ac19cSjeremylt ierr = CeedFree(&impl->qdata); CeedChk(ierr); 41885ac19cSjeremylt 42885ac19cSjeremylt ierr = CeedFree(&impl->indata); CeedChk(ierr); 43885ac19cSjeremylt ierr = CeedFree(&impl->outdata); CeedChk(ierr); 44885ac19cSjeremylt 4521617c04Sjeremylt ierr = CeedFree(&op->data); CeedChk(ierr); 4621617c04Sjeremylt return 0; 4721617c04Sjeremylt } 4821617c04Sjeremylt 49885ac19cSjeremylt /* 50885ac19cSjeremylt Setup infields or outfields 51885ac19cSjeremylt */ 52885ac19cSjeremylt static int CeedOperatorSetupFields_Ref(struct CeedQFunctionField qfields[16], 53885ac19cSjeremylt struct CeedOperatorField ofields[16], 54885ac19cSjeremylt CeedVector *evecs, CeedScalar **qdata, 55885ac19cSjeremylt CeedScalar **qdata_alloc, CeedScalar **indata, 56885ac19cSjeremylt CeedInt starti, CeedInt starte, 57885ac19cSjeremylt CeedInt startq, CeedInt numfields, CeedInt Q) { 58885ac19cSjeremylt CeedInt dim, ierr, ie=starte, iq=startq, ncomp; 5921617c04Sjeremylt 60885ac19cSjeremylt // Loop over fields 61885ac19cSjeremylt for (CeedInt i=0; i<numfields; i++) { 62885ac19cSjeremylt if (ofields[i].Erestrict) { 63885ac19cSjeremylt ierr = CeedElemRestrictionCreateVector(ofields[i].Erestrict, NULL, &evecs[ie]); 6421617c04Sjeremylt CeedChk(ierr); 65885ac19cSjeremylt ie++; 6621617c04Sjeremylt } 67885ac19cSjeremylt CeedEvalMode emode = qfields[i].emode; 68885ac19cSjeremylt switch(emode) { 69885ac19cSjeremylt case CEED_EVAL_NONE: 70885ac19cSjeremylt break; // No action 71885ac19cSjeremylt case CEED_EVAL_INTERP: 72885ac19cSjeremylt ncomp = qfields[i].ncomp; 73885ac19cSjeremylt ierr = CeedMalloc(Q*ncomp, &qdata_alloc[iq]); CeedChk(ierr); 74885ac19cSjeremylt qdata[i + starti] = qdata_alloc[iq]; 75885ac19cSjeremylt iq++; 76885ac19cSjeremylt break; 77885ac19cSjeremylt case CEED_EVAL_GRAD: 78885ac19cSjeremylt ncomp = qfields[i].ncomp; 79885ac19cSjeremylt dim = ofields[i].basis->dim; 80885ac19cSjeremylt ierr = CeedMalloc(Q*ncomp*dim, &qdata_alloc[iq]); CeedChk(ierr); 81885ac19cSjeremylt qdata[i + starti] = qdata_alloc[iq]; 82885ac19cSjeremylt iq++; 83885ac19cSjeremylt break; 84885ac19cSjeremylt case CEED_EVAL_WEIGHT: // Only on input fields 85885ac19cSjeremylt ierr = CeedMalloc(Q, &qdata_alloc[iq]); CeedChk(ierr); 86885ac19cSjeremylt ierr = CeedBasisApply(ofields[iq].basis, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 87885ac19cSjeremylt NULL, qdata_alloc[iq]); CeedChk(ierr); 88885ac19cSjeremylt qdata[i] = qdata_alloc[iq]; 89885ac19cSjeremylt indata[i] = qdata[i]; 90885ac19cSjeremylt iq++; 91885ac19cSjeremylt break; 92885ac19cSjeremylt case CEED_EVAL_DIV: 93885ac19cSjeremylt break; // Not implimented 94885ac19cSjeremylt case CEED_EVAL_CURL: 95885ac19cSjeremylt break; // Not implimented 9621617c04Sjeremylt } 97885ac19cSjeremylt } 9821617c04Sjeremylt return 0; 9921617c04Sjeremylt } 10021617c04Sjeremylt 101885ac19cSjeremylt /* 102885ac19cSjeremylt CeedOperator needs to connect all the named fields (be they active or passive) 103885ac19cSjeremylt to the named inputs and outputs of its CeedQFunction. 104885ac19cSjeremylt */ 105885ac19cSjeremylt static int CeedOperatorSetup_Ref(CeedOperator op) { 106885ac19cSjeremylt if (op->setupdone) return 0; 107885ac19cSjeremylt CeedOperator_Ref *opref = op->data; 108885ac19cSjeremylt CeedQFunction qf = op->qf; 109885ac19cSjeremylt CeedInt Q = op->numqpoints; 11021617c04Sjeremylt int ierr; 11121617c04Sjeremylt 112885ac19cSjeremylt // Count infield and outfield array sizes and evectors 113885ac19cSjeremylt for (CeedInt i=0; i<qf->numinputfields; i++) { 114885ac19cSjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 115885ac19cSjeremylt opref->numqin += !!(emode & CEED_EVAL_INTERP) + !!(emode & CEED_EVAL_GRAD) + !! 116885ac19cSjeremylt (emode & CEED_EVAL_WEIGHT); 117885ac19cSjeremylt opref->numein += 118885ac19cSjeremylt !!op->inputfields[i].Erestrict; // Need E-vector when restriction exists 11921617c04Sjeremylt } 120885ac19cSjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 121885ac19cSjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 122885ac19cSjeremylt opref->numqout += !!(emode & CEED_EVAL_INTERP) + !!(emode & CEED_EVAL_GRAD); 123885ac19cSjeremylt opref->numeout += !!op->outputfields[i].Erestrict; 124885ac19cSjeremylt } 125885ac19cSjeremylt 126885ac19cSjeremylt // Allocate 127885ac19cSjeremylt ierr = CeedCalloc(opref->numein + opref->numeout, &opref->evecs); CeedChk(ierr); 128885ac19cSjeremylt ierr = CeedCalloc(qf->numinputfields + qf->numoutputfields, &opref->edata); 129885ac19cSjeremylt CeedChk(ierr); 130885ac19cSjeremylt 131885ac19cSjeremylt ierr = CeedCalloc(opref->numqin + opref->numqout, &opref->qdata_alloc); 132885ac19cSjeremylt CeedChk(ierr); 133885ac19cSjeremylt ierr = CeedCalloc(qf->numinputfields + qf->numoutputfields, &opref->qdata); 134885ac19cSjeremylt CeedChk(ierr); 135885ac19cSjeremylt 136885ac19cSjeremylt ierr = CeedCalloc(16, &opref->indata); CeedChk(ierr); 137885ac19cSjeremylt ierr = CeedCalloc(16, &opref->outdata); CeedChk(ierr); 138885ac19cSjeremylt 139885ac19cSjeremylt // Set up infield and outfield pointer arrays 140885ac19cSjeremylt // Infields 141885ac19cSjeremylt ierr = CeedOperatorSetupFields_Ref(qf->inputfields, op->inputfields, 142885ac19cSjeremylt opref->evecs, opref->qdata, opref->qdata_alloc, 143885ac19cSjeremylt opref->indata, 0, 0, 0, 144885ac19cSjeremylt qf->numinputfields, Q); CeedChk(ierr); 145885ac19cSjeremylt 146885ac19cSjeremylt // Outfields 147885ac19cSjeremylt ierr = CeedOperatorSetupFields_Ref(qf->outputfields, op->outputfields, 148885ac19cSjeremylt opref->evecs, opref->qdata, opref->qdata_alloc, 149885ac19cSjeremylt opref->indata, qf->numinputfields, opref->numein, 150885ac19cSjeremylt opref->numqin, qf->numoutputfields, Q); CeedChk(ierr); 151885ac19cSjeremylt 152*7ca8db16Sjeremylt // Output Qvecs 153*7ca8db16Sjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 154*7ca8db16Sjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 155*7ca8db16Sjeremylt if (emode != CEED_EVAL_NONE) { 156*7ca8db16Sjeremylt opref->outdata[i] = opref->qdata[i + qf->numinputfields]; 157*7ca8db16Sjeremylt } 158*7ca8db16Sjeremylt } 159*7ca8db16Sjeremylt 160885ac19cSjeremylt op->setupdone = 1; 161885ac19cSjeremylt 162885ac19cSjeremylt return 0; 163885ac19cSjeremylt } 164885ac19cSjeremylt 165885ac19cSjeremylt static int CeedOperatorApply_Ref(CeedOperator op, CeedVector invec, 166885ac19cSjeremylt CeedVector outvec, CeedRequest *request) { 167885ac19cSjeremylt CeedOperator_Ref *opref = op->data; 168885ac19cSjeremylt CeedInt Q = op->numqpoints, elemsize; 169885ac19cSjeremylt int ierr; 170885ac19cSjeremylt CeedQFunction qf = op->qf; 171885ac19cSjeremylt CeedTransposeMode lmode = CEED_NOTRANSPOSE; 172*7ca8db16Sjeremylt CeedScalar *vec_temp; 173885ac19cSjeremylt 174885ac19cSjeremylt // Setup 175885ac19cSjeremylt ierr = CeedOperatorSetup_Ref(op); CeedChk(ierr); 176885ac19cSjeremylt 177885ac19cSjeremylt // Input Evecs and Restriction 178885ac19cSjeremylt for (CeedInt i=0,iein=0; i<qf->numinputfields; i++) { 179885ac19cSjeremylt // Restriction 180885ac19cSjeremylt if (op->inputfields[i].Erestrict) { 181*7ca8db16Sjeremylt // Zero evec 182*7ca8db16Sjeremylt ierr = CeedVectorGetArray(opref->evecs[iein], CEED_MEM_HOST, &vec_temp); CeedChk(ierr); 183*7ca8db16Sjeremylt for (CeedInt j=0; j<opref->evecs[iein]->length; j++) 184*7ca8db16Sjeremylt vec_temp[j] = 0.; 185*7ca8db16Sjeremylt ierr = CeedVectorRestoreArray(opref->evecs[iein], &vec_temp); CeedChk(ierr); 186885ac19cSjeremylt // Passive 187885ac19cSjeremylt if (op->inputfields[i].vec) { 188*7ca8db16Sjeremylt // Restrict 189885ac19cSjeremylt ierr = CeedElemRestrictionApply(op->inputfields[i].Erestrict, CEED_NOTRANSPOSE, 190885ac19cSjeremylt lmode, op->inputfields[i].vec, opref->evecs[iein], 191885ac19cSjeremylt request); CeedChk(ierr); 192*7ca8db16Sjeremylt // Get evec 193885ac19cSjeremylt ierr = CeedVectorGetArrayRead(opref->evecs[iein], CEED_MEM_HOST, 194885ac19cSjeremylt (const CeedScalar **) &opref->edata[i]); CeedChk(ierr); 195885ac19cSjeremylt iein++; 196885ac19cSjeremylt } else { 197885ac19cSjeremylt // Active 198*7ca8db16Sjeremylt // Restrict 199*7ca8db16Sjeremylt 200885ac19cSjeremylt ierr = CeedElemRestrictionApply(op->inputfields[i].Erestrict, CEED_NOTRANSPOSE, 201885ac19cSjeremylt lmode, invec, opref->evecs[iein], request); CeedChk(ierr); 202*7ca8db16Sjeremylt // Get evec 203885ac19cSjeremylt ierr = CeedVectorGetArrayRead(opref->evecs[iein], CEED_MEM_HOST, 204885ac19cSjeremylt (const CeedScalar **) &opref->edata[i]); CeedChk(ierr); 205885ac19cSjeremylt iein++; 206885ac19cSjeremylt } 207885ac19cSjeremylt } else { 208885ac19cSjeremylt // No restriction 209885ac19cSjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 210885ac19cSjeremylt if (emode & CEED_EVAL_WEIGHT) { 211885ac19cSjeremylt } else { 212*7ca8db16Sjeremylt // Passive 213*7ca8db16Sjeremylt if (op->inputfields[i].vec) { 214885ac19cSjeremylt ierr = CeedVectorGetArrayRead(op->inputfields[i].vec, CEED_MEM_HOST, 215885ac19cSjeremylt (const CeedScalar **) &opref->edata[i]); CeedChk(ierr); 216*7ca8db16Sjeremylt // Active 217*7ca8db16Sjeremylt } else { 218*7ca8db16Sjeremylt ierr = CeedVectorGetArrayRead(invec, CEED_MEM_HOST, 219*7ca8db16Sjeremylt (const CeedScalar **) &opref->edata[i]); CeedChk(ierr); 220*7ca8db16Sjeremylt } 221885ac19cSjeremylt } 222885ac19cSjeremylt } 223885ac19cSjeremylt } 224885ac19cSjeremylt 225885ac19cSjeremylt // Output Evecs 226885ac19cSjeremylt for (CeedInt i=0,ieout=opref->numein; i<qf->numoutputfields; i++) { 227885ac19cSjeremylt // Restriction 228885ac19cSjeremylt if (op->outputfields[i].Erestrict) { 229885ac19cSjeremylt ierr = CeedVectorGetArray(opref->evecs[ieout], CEED_MEM_HOST, 230885ac19cSjeremylt &opref->edata[i + qf->numinputfields]); CeedChk(ierr); 231885ac19cSjeremylt ieout++; 232885ac19cSjeremylt } else { 233885ac19cSjeremylt // No restriction 234885ac19cSjeremylt // Passive 235885ac19cSjeremylt if (op->inputfields[i].vec) { 236*7ca8db16Sjeremylt ierr = CeedVectorGetArray(op->outputfields[i].vec, CEED_MEM_HOST, 237885ac19cSjeremylt &opref->edata[i + qf->numinputfields]); CeedChk(ierr); 238885ac19cSjeremylt } else { 239885ac19cSjeremylt // Active 240885ac19cSjeremylt ierr = CeedVectorGetArray(outvec, CEED_MEM_HOST, 241885ac19cSjeremylt &opref->edata[i + qf->numinputfields]); CeedChk(ierr); 242885ac19cSjeremylt } 243885ac19cSjeremylt } 244885ac19cSjeremylt } 245885ac19cSjeremylt 246885ac19cSjeremylt // Loop through elements 247885ac19cSjeremylt for (CeedInt e=0; e<op->numelements; e++) { 248885ac19cSjeremylt // Input basis apply if needed 249885ac19cSjeremylt for (CeedInt i=0; i<qf->numinputfields; i++) { 250885ac19cSjeremylt // Get elemsize 251885ac19cSjeremylt if (op->inputfields[i].Erestrict) { 252885ac19cSjeremylt elemsize = op->inputfields[i].Erestrict->elemsize; 253885ac19cSjeremylt } else { 254885ac19cSjeremylt elemsize = Q; 255885ac19cSjeremylt } 256885ac19cSjeremylt // Get emode, ncomp 257885ac19cSjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 258885ac19cSjeremylt CeedInt ncomp = qf->inputfields[i].ncomp; 259885ac19cSjeremylt // Basis action 260885ac19cSjeremylt switch(emode) { 261885ac19cSjeremylt case CEED_EVAL_NONE: 262885ac19cSjeremylt opref->indata[i] = &opref->edata[i][e*Q*ncomp]; 263885ac19cSjeremylt break; 264885ac19cSjeremylt case CEED_EVAL_INTERP: 265885ac19cSjeremylt ierr = CeedBasisApply(op->inputfields[i].basis, CEED_NOTRANSPOSE, 266885ac19cSjeremylt CEED_EVAL_INTERP, &opref->edata[i][e*elemsize*ncomp], opref->qdata[i]); 267885ac19cSjeremylt CeedChk(ierr); 268885ac19cSjeremylt opref->indata[i] = opref->qdata[i]; 269885ac19cSjeremylt break; 270885ac19cSjeremylt case CEED_EVAL_GRAD: 271885ac19cSjeremylt ierr = CeedBasisApply(op->inputfields[i].basis, CEED_NOTRANSPOSE, 272885ac19cSjeremylt CEED_EVAL_GRAD, &opref->edata[i][e*elemsize*ncomp], opref->qdata[i]); 273885ac19cSjeremylt CeedChk(ierr); 274885ac19cSjeremylt opref->indata[i] = opref->qdata[i]; 275885ac19cSjeremylt break; 276885ac19cSjeremylt case CEED_EVAL_WEIGHT: 277885ac19cSjeremylt break; // No action 278885ac19cSjeremylt case CEED_EVAL_DIV: 279885ac19cSjeremylt break; // Not implimented 280885ac19cSjeremylt case CEED_EVAL_CURL: 281885ac19cSjeremylt break; // Not implimented 282885ac19cSjeremylt } 283885ac19cSjeremylt } 284885ac19cSjeremylt // Output pointers 285885ac19cSjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 286885ac19cSjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 287885ac19cSjeremylt if (emode == CEED_EVAL_NONE) { 288885ac19cSjeremylt CeedInt ncomp = qf->outputfields[i].ncomp; 289885ac19cSjeremylt opref->outdata[i] = &opref->edata[i + qf->numinputfields][e*Q*ncomp]; 290885ac19cSjeremylt } 291885ac19cSjeremylt } 292885ac19cSjeremylt // Q function 293885ac19cSjeremylt ierr = CeedQFunctionApply(op->qf, Q, (const CeedScalar * const*) opref->indata, 294885ac19cSjeremylt opref->outdata); CeedChk(ierr); 295885ac19cSjeremylt 296885ac19cSjeremylt // Output basis apply if needed 297885ac19cSjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 298885ac19cSjeremylt // Get elemsize 299885ac19cSjeremylt if (op->outputfields[i].Erestrict) { 300885ac19cSjeremylt elemsize = op->outputfields[i].Erestrict->elemsize; 301885ac19cSjeremylt } else { 302885ac19cSjeremylt elemsize = Q; 303885ac19cSjeremylt } 304885ac19cSjeremylt // Get emode, ncomp 305885ac19cSjeremylt CeedInt ncomp = qf->outputfields[i].ncomp; 306885ac19cSjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 307885ac19cSjeremylt // Basis action 308885ac19cSjeremylt switch(emode) { 309885ac19cSjeremylt case CEED_EVAL_NONE: 310885ac19cSjeremylt break; // No action 311885ac19cSjeremylt case CEED_EVAL_INTERP: 312885ac19cSjeremylt ierr = CeedBasisApply(op->outputfields[i].basis, CEED_TRANSPOSE, 313885ac19cSjeremylt CEED_EVAL_INTERP, opref->outdata[i], 314885ac19cSjeremylt &opref->edata[i + qf->numinputfields][e*elemsize*ncomp]); CeedChk(ierr); 315885ac19cSjeremylt break; 316885ac19cSjeremylt case CEED_EVAL_GRAD: 317885ac19cSjeremylt ierr = CeedBasisApply(op->outputfields[i].basis, CEED_TRANSPOSE, CEED_EVAL_GRAD, 318885ac19cSjeremylt opref->outdata[i], &opref->edata[i + qf->numinputfields][e*elemsize*ncomp]); 319885ac19cSjeremylt CeedChk(ierr); 320885ac19cSjeremylt break; 321885ac19cSjeremylt case CEED_EVAL_WEIGHT: 322885ac19cSjeremylt break; // Should not occur 323885ac19cSjeremylt case CEED_EVAL_DIV: 324885ac19cSjeremylt break; // Not implimented 325885ac19cSjeremylt case CEED_EVAL_CURL: 326885ac19cSjeremylt break; // Not implimented 327885ac19cSjeremylt } 328885ac19cSjeremylt } 329885ac19cSjeremylt } 330885ac19cSjeremylt 331885ac19cSjeremylt // Output restriction 332885ac19cSjeremylt for (CeedInt i=0,ieout=opref->numein; i<qf->numoutputfields; i++) { 333885ac19cSjeremylt // Restriction 334885ac19cSjeremylt if (op->outputfields[i].Erestrict) { 335885ac19cSjeremylt // Passive 336885ac19cSjeremylt if (op->outputfields[i].vec) { 337*7ca8db16Sjeremylt // Restore evec 338885ac19cSjeremylt ierr = CeedVectorRestoreArray(opref->evecs[ieout], 339885ac19cSjeremylt &opref->edata[i + qf->numinputfields]); CeedChk(ierr); 340*7ca8db16Sjeremylt // Zero lvec 341*7ca8db16Sjeremylt ierr = CeedVectorGetArray(op->outputfields[i].vec, CEED_MEM_HOST, &vec_temp); CeedChk(ierr); 342*7ca8db16Sjeremylt for (CeedInt j=0; j<op->outputfields[i].vec->length; j++) 343*7ca8db16Sjeremylt vec_temp[j] = 0.; 344*7ca8db16Sjeremylt ierr = CeedVectorRestoreArray(op->outputfields[i].vec, &vec_temp); CeedChk(ierr); 345*7ca8db16Sjeremylt // Restrict 346885ac19cSjeremylt ierr = CeedElemRestrictionApply(op->outputfields[i].Erestrict, CEED_TRANSPOSE, 347885ac19cSjeremylt lmode, opref->evecs[ieout], op->outputfields[i].vec, request); CeedChk(ierr); 348885ac19cSjeremylt ieout++; 349885ac19cSjeremylt } else { 350885ac19cSjeremylt // Active 351*7ca8db16Sjeremylt // Restore evec 352885ac19cSjeremylt ierr = CeedVectorRestoreArray(opref->evecs[ieout], 353885ac19cSjeremylt &opref->edata[i + qf->numinputfields]); CeedChk(ierr); 354*7ca8db16Sjeremylt // Zero lvec 355*7ca8db16Sjeremylt ierr = CeedVectorGetArray(outvec, CEED_MEM_HOST, &vec_temp); CeedChk(ierr); 356*7ca8db16Sjeremylt for (CeedInt j=0; j<outvec->length; j++) 357*7ca8db16Sjeremylt vec_temp[j] = 0.; 358*7ca8db16Sjeremylt ierr = CeedVectorRestoreArray(outvec, &vec_temp); CeedChk(ierr); 359*7ca8db16Sjeremylt // Restrict 360885ac19cSjeremylt ierr = CeedElemRestrictionApply(op->outputfields[i].Erestrict, CEED_TRANSPOSE, 361885ac19cSjeremylt lmode, opref->evecs[ieout], outvec, request); CeedChk(ierr); 362885ac19cSjeremylt ieout++; 363885ac19cSjeremylt } 364885ac19cSjeremylt } else { 365885ac19cSjeremylt // No Restriction 366885ac19cSjeremylt // Passive 367885ac19cSjeremylt if (op->outputfields[i].vec) { 368885ac19cSjeremylt ierr = CeedVectorRestoreArray(op->outputfields[i].vec, 369885ac19cSjeremylt &opref->edata[i + qf->numinputfields]); CeedChk(ierr); 370885ac19cSjeremylt } else { 371885ac19cSjeremylt // Active 372885ac19cSjeremylt ierr = CeedVectorRestoreArray(outvec, &opref->edata[i + qf->numinputfields]); 373885ac19cSjeremylt CeedChk(ierr); 374885ac19cSjeremylt } 375885ac19cSjeremylt } 376885ac19cSjeremylt } 377885ac19cSjeremylt 378*7ca8db16Sjeremylt // Restore input arrays 379*7ca8db16Sjeremylt for (CeedInt i=0,iein=0; i<qf->numinputfields; i++) { 380*7ca8db16Sjeremylt // Restriction 381*7ca8db16Sjeremylt if (op->inputfields[i].Erestrict) { 382*7ca8db16Sjeremylt ierr = CeedVectorRestoreArrayRead(opref->evecs[iein], 383*7ca8db16Sjeremylt (const CeedScalar **) &opref->edata[i]); CeedChk(ierr); 384*7ca8db16Sjeremylt iein++; 385*7ca8db16Sjeremylt } else { 386*7ca8db16Sjeremylt // No restriction 387*7ca8db16Sjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 388*7ca8db16Sjeremylt if (emode & CEED_EVAL_WEIGHT) { 389*7ca8db16Sjeremylt } else { 390*7ca8db16Sjeremylt // Passive 391*7ca8db16Sjeremylt if (op->inputfields[i].vec) { 392*7ca8db16Sjeremylt ierr = CeedVectorRestoreArrayRead(op->inputfields[i].vec, 393*7ca8db16Sjeremylt (const CeedScalar **) &opref->edata[i]); CeedChk(ierr); 394*7ca8db16Sjeremylt // Active 395*7ca8db16Sjeremylt } else { 396*7ca8db16Sjeremylt ierr = CeedVectorRestoreArrayRead(invec, 397*7ca8db16Sjeremylt (const CeedScalar **) &opref->edata[i]); CeedChk(ierr); 398*7ca8db16Sjeremylt 399*7ca8db16Sjeremylt } 400*7ca8db16Sjeremylt } 401*7ca8db16Sjeremylt } 402*7ca8db16Sjeremylt } 403*7ca8db16Sjeremylt 40421617c04Sjeremylt return 0; 40521617c04Sjeremylt } 40621617c04Sjeremylt 40721617c04Sjeremylt int CeedOperatorCreate_Ref(CeedOperator op) { 40821617c04Sjeremylt CeedOperator_Ref *impl; 40921617c04Sjeremylt int ierr; 41021617c04Sjeremylt 41121617c04Sjeremylt ierr = CeedCalloc(1, &impl); CeedChk(ierr); 41221617c04Sjeremylt op->data = impl; 41321617c04Sjeremylt op->Destroy = CeedOperatorDestroy_Ref; 41421617c04Sjeremylt op->Apply = CeedOperatorApply_Ref; 41521617c04Sjeremylt return 0; 41621617c04Sjeremylt } 417