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 CeedOperator_Ref *impl = op->data; 2321617c04Sjeremylt int 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 31885ac19cSjeremylt for (CeedInt i=0; i<impl->numqin+impl->numqout; i++) { 32885ac19cSjeremylt ierr = CeedFree(&impl->qdata_alloc[i]); CeedChk(ierr); 33885ac19cSjeremylt } 34885ac19cSjeremylt ierr = CeedFree(&impl->qdata_alloc); CeedChk(ierr); 35885ac19cSjeremylt ierr = CeedFree(&impl->qdata); CeedChk(ierr); 36885ac19cSjeremylt 37885ac19cSjeremylt ierr = CeedFree(&impl->indata); CeedChk(ierr); 38885ac19cSjeremylt ierr = CeedFree(&impl->outdata); CeedChk(ierr); 39885ac19cSjeremylt 4021617c04Sjeremylt ierr = CeedFree(&op->data); CeedChk(ierr); 4121617c04Sjeremylt return 0; 4221617c04Sjeremylt } 4321617c04Sjeremylt 44885ac19cSjeremylt /* 45885ac19cSjeremylt Setup infields or outfields 46885ac19cSjeremylt */ 47885ac19cSjeremylt static int CeedOperatorSetupFields_Ref(struct CeedQFunctionField qfields[16], 48885ac19cSjeremylt struct CeedOperatorField ofields[16], 49885ac19cSjeremylt CeedVector *evecs, CeedScalar **qdata, 50885ac19cSjeremylt CeedScalar **qdata_alloc, CeedScalar **indata, 51885ac19cSjeremylt CeedInt starti, CeedInt starte, 52885ac19cSjeremylt CeedInt startq, CeedInt numfields, CeedInt Q) { 53885ac19cSjeremylt CeedInt dim, ierr, ie=starte, iq=startq, ncomp; 5421617c04Sjeremylt 55885ac19cSjeremylt // Loop over fields 56885ac19cSjeremylt for (CeedInt i=0; i<numfields; i++) { 57668048e2SJed Brown if (ofields[i].Erestrict != CEED_RESTRICTION_IDENTITY) { 58885ac19cSjeremylt ierr = CeedElemRestrictionCreateVector(ofields[i].Erestrict, NULL, &evecs[ie]); 5921617c04Sjeremylt CeedChk(ierr); 60885ac19cSjeremylt ie++; 6121617c04Sjeremylt } 62885ac19cSjeremylt CeedEvalMode emode = qfields[i].emode; 63885ac19cSjeremylt switch(emode) { 64885ac19cSjeremylt case CEED_EVAL_NONE: 65885ac19cSjeremylt break; // No action 66885ac19cSjeremylt case CEED_EVAL_INTERP: 67885ac19cSjeremylt ncomp = qfields[i].ncomp; 68885ac19cSjeremylt ierr = CeedMalloc(Q*ncomp, &qdata_alloc[iq]); CeedChk(ierr); 69885ac19cSjeremylt qdata[i + starti] = qdata_alloc[iq]; 70885ac19cSjeremylt iq++; 71885ac19cSjeremylt break; 72885ac19cSjeremylt case CEED_EVAL_GRAD: 73885ac19cSjeremylt ncomp = qfields[i].ncomp; 74885ac19cSjeremylt dim = ofields[i].basis->dim; 75885ac19cSjeremylt ierr = CeedMalloc(Q*ncomp*dim, &qdata_alloc[iq]); CeedChk(ierr); 76885ac19cSjeremylt qdata[i + starti] = qdata_alloc[iq]; 77885ac19cSjeremylt iq++; 78885ac19cSjeremylt break; 79885ac19cSjeremylt case CEED_EVAL_WEIGHT: // Only on input fields 80885ac19cSjeremylt ierr = CeedMalloc(Q, &qdata_alloc[iq]); CeedChk(ierr); 81d3181881Sjeremylt ierr = CeedBasisApply(ofields[iq].basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 82885ac19cSjeremylt NULL, qdata_alloc[iq]); CeedChk(ierr); 83885ac19cSjeremylt qdata[i] = qdata_alloc[iq]; 84885ac19cSjeremylt indata[i] = qdata[i]; 85885ac19cSjeremylt iq++; 86885ac19cSjeremylt break; 87885ac19cSjeremylt case CEED_EVAL_DIV: 88885ac19cSjeremylt break; // Not implimented 89885ac19cSjeremylt case CEED_EVAL_CURL: 90885ac19cSjeremylt break; // Not implimented 9121617c04Sjeremylt } 92885ac19cSjeremylt } 9321617c04Sjeremylt return 0; 9421617c04Sjeremylt } 9521617c04Sjeremylt 96885ac19cSjeremylt /* 97885ac19cSjeremylt CeedOperator needs to connect all the named fields (be they active or passive) 98885ac19cSjeremylt to the named inputs and outputs of its CeedQFunction. 99885ac19cSjeremylt */ 100885ac19cSjeremylt static int CeedOperatorSetup_Ref(CeedOperator op) { 101885ac19cSjeremylt if (op->setupdone) return 0; 102885ac19cSjeremylt CeedOperator_Ref *opref = op->data; 103885ac19cSjeremylt CeedQFunction qf = op->qf; 104885ac19cSjeremylt CeedInt Q = op->numqpoints; 10521617c04Sjeremylt int ierr; 10621617c04Sjeremylt 107885ac19cSjeremylt // Count infield and outfield array sizes and evectors 108885ac19cSjeremylt for (CeedInt i=0; i<qf->numinputfields; i++) { 109885ac19cSjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 110885ac19cSjeremylt opref->numqin += !!(emode & CEED_EVAL_INTERP) + !!(emode & CEED_EVAL_GRAD) + !! 111885ac19cSjeremylt (emode & CEED_EVAL_WEIGHT); 112885ac19cSjeremylt opref->numein += 113*0c7a96bbSjeremylt (op->inputfields[i].Erestrict != 114*0c7a96bbSjeremylt CEED_RESTRICTION_IDENTITY); // Need E-vector when non-identity restriction exists 11521617c04Sjeremylt } 116885ac19cSjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 117885ac19cSjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 118885ac19cSjeremylt opref->numqout += !!(emode & CEED_EVAL_INTERP) + !!(emode & CEED_EVAL_GRAD); 119cb661df1Sjeremylt opref->numeout += (op->outputfields[i].Erestrict != CEED_RESTRICTION_IDENTITY); 120885ac19cSjeremylt } 121885ac19cSjeremylt 122885ac19cSjeremylt // Allocate 123885ac19cSjeremylt ierr = CeedCalloc(opref->numein + opref->numeout, &opref->evecs); CeedChk(ierr); 124885ac19cSjeremylt ierr = CeedCalloc(qf->numinputfields + qf->numoutputfields, &opref->edata); 125885ac19cSjeremylt CeedChk(ierr); 126885ac19cSjeremylt 127885ac19cSjeremylt ierr = CeedCalloc(opref->numqin + opref->numqout, &opref->qdata_alloc); 128885ac19cSjeremylt CeedChk(ierr); 129885ac19cSjeremylt ierr = CeedCalloc(qf->numinputfields + qf->numoutputfields, &opref->qdata); 130885ac19cSjeremylt CeedChk(ierr); 131885ac19cSjeremylt 132885ac19cSjeremylt ierr = CeedCalloc(16, &opref->indata); CeedChk(ierr); 133885ac19cSjeremylt ierr = CeedCalloc(16, &opref->outdata); CeedChk(ierr); 134885ac19cSjeremylt 135885ac19cSjeremylt // Set up infield and outfield pointer arrays 136885ac19cSjeremylt // Infields 137885ac19cSjeremylt ierr = CeedOperatorSetupFields_Ref(qf->inputfields, op->inputfields, 138885ac19cSjeremylt opref->evecs, opref->qdata, opref->qdata_alloc, 139885ac19cSjeremylt opref->indata, 0, 0, 0, 140885ac19cSjeremylt qf->numinputfields, Q); CeedChk(ierr); 141885ac19cSjeremylt 142885ac19cSjeremylt // Outfields 143885ac19cSjeremylt ierr = CeedOperatorSetupFields_Ref(qf->outputfields, op->outputfields, 144885ac19cSjeremylt opref->evecs, opref->qdata, opref->qdata_alloc, 145885ac19cSjeremylt opref->indata, qf->numinputfields, opref->numein, 146885ac19cSjeremylt opref->numqin, qf->numoutputfields, Q); CeedChk(ierr); 147885ac19cSjeremylt 1487ca8db16Sjeremylt // Output Qvecs 1497ca8db16Sjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 1507ca8db16Sjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 1517ca8db16Sjeremylt if (emode != CEED_EVAL_NONE) { 1527ca8db16Sjeremylt opref->outdata[i] = opref->qdata[i + qf->numinputfields]; 1537ca8db16Sjeremylt } 1547ca8db16Sjeremylt } 1557ca8db16Sjeremylt 156885ac19cSjeremylt op->setupdone = 1; 157885ac19cSjeremylt 158885ac19cSjeremylt return 0; 159885ac19cSjeremylt } 160885ac19cSjeremylt 161885ac19cSjeremylt static int CeedOperatorApply_Ref(CeedOperator op, CeedVector invec, 162885ac19cSjeremylt CeedVector outvec, CeedRequest *request) { 163885ac19cSjeremylt CeedOperator_Ref *opref = op->data; 164885ac19cSjeremylt CeedInt Q = op->numqpoints, elemsize; 165885ac19cSjeremylt int ierr; 166885ac19cSjeremylt CeedQFunction qf = op->qf; 167885ac19cSjeremylt CeedTransposeMode lmode = CEED_NOTRANSPOSE; 1687ca8db16Sjeremylt CeedScalar *vec_temp; 169885ac19cSjeremylt 170885ac19cSjeremylt // Setup 171885ac19cSjeremylt ierr = CeedOperatorSetup_Ref(op); CeedChk(ierr); 172885ac19cSjeremylt 173885ac19cSjeremylt // Input Evecs and Restriction 174885ac19cSjeremylt for (CeedInt i=0,iein=0; i<qf->numinputfields; i++) { 175668048e2SJed Brown // No Restriction 176668048e2SJed Brown if (op->inputfields[i].Erestrict == CEED_RESTRICTION_IDENTITY) { 177668048e2SJed Brown CeedEvalMode emode = qf->inputfields[i].emode; 178668048e2SJed Brown if (emode & CEED_EVAL_WEIGHT) { 179668048e2SJed Brown } else { 180668048e2SJed Brown // Active 181668048e2SJed Brown if (op->inputfields[i].vec == CEED_VECTOR_ACTIVE) { 182668048e2SJed Brown ierr = CeedVectorGetArrayRead(invec, CEED_MEM_HOST, 183668048e2SJed Brown (const CeedScalar **) &opref->edata[i]); CeedChk(ierr); 184668048e2SJed Brown // Passive 185668048e2SJed Brown } else { 186668048e2SJed Brown ierr = CeedVectorGetArrayRead(op->inputfields[i].vec, CEED_MEM_HOST, 187668048e2SJed Brown (const CeedScalar **) &opref->edata[i]); CeedChk(ierr); 188668048e2SJed Brown } 189668048e2SJed Brown } 190668048e2SJed Brown } else { 191885ac19cSjeremylt // Restriction 1927ca8db16Sjeremylt // Zero evec 1930f5de9e9Sjeremylt ierr = CeedVectorGetArray(opref->evecs[iein], CEED_MEM_HOST, &vec_temp); 1940f5de9e9Sjeremylt CeedChk(ierr); 1957ca8db16Sjeremylt for (CeedInt j=0; j<opref->evecs[iein]->length; j++) 1967ca8db16Sjeremylt vec_temp[j] = 0.; 1977ca8db16Sjeremylt ierr = CeedVectorRestoreArray(opref->evecs[iein], &vec_temp); CeedChk(ierr); 198668048e2SJed Brown // Active 199668048e2SJed Brown if (op->inputfields[i].vec == CEED_VECTOR_ACTIVE) { 200668048e2SJed Brown // Restrict 201668048e2SJed Brown ierr = CeedElemRestrictionApply(op->inputfields[i].Erestrict, CEED_NOTRANSPOSE, 202668048e2SJed Brown lmode, invec, opref->evecs[iein], 203668048e2SJed Brown request); CeedChk(ierr); 204668048e2SJed Brown // Get evec 205668048e2SJed Brown ierr = CeedVectorGetArrayRead(opref->evecs[iein], CEED_MEM_HOST, 206668048e2SJed Brown (const CeedScalar **) &opref->edata[i]); CeedChk(ierr); 207668048e2SJed Brown iein++; 208668048e2SJed Brown } else { 209885ac19cSjeremylt // Passive 2107ca8db16Sjeremylt // Restrict 211885ac19cSjeremylt ierr = CeedElemRestrictionApply(op->inputfields[i].Erestrict, CEED_NOTRANSPOSE, 212885ac19cSjeremylt lmode, op->inputfields[i].vec, opref->evecs[iein], 213885ac19cSjeremylt request); CeedChk(ierr); 2147ca8db16Sjeremylt // Get evec 215885ac19cSjeremylt ierr = CeedVectorGetArrayRead(opref->evecs[iein], CEED_MEM_HOST, 216885ac19cSjeremylt (const CeedScalar **) &opref->edata[i]); CeedChk(ierr); 217885ac19cSjeremylt iein++; 218885ac19cSjeremylt } 219885ac19cSjeremylt } 220885ac19cSjeremylt } 221885ac19cSjeremylt 222885ac19cSjeremylt // Output Evecs 223885ac19cSjeremylt for (CeedInt i=0,ieout=opref->numein; i<qf->numoutputfields; i++) { 224668048e2SJed Brown // No Restriction 225668048e2SJed Brown if (op->outputfields[i].Erestrict == CEED_RESTRICTION_IDENTITY) { 226668048e2SJed Brown // Active 227668048e2SJed Brown if (op->outputfields[i].vec == CEED_VECTOR_ACTIVE) { 228668048e2SJed Brown ierr = CeedVectorGetArray(outvec, CEED_MEM_HOST, 229668048e2SJed Brown &opref->edata[i + qf->numinputfields]); CeedChk(ierr); 230668048e2SJed Brown } else { 231668048e2SJed Brown // Passive 232668048e2SJed Brown ierr = CeedVectorGetArray(op->outputfields[i].vec, CEED_MEM_HOST, 233668048e2SJed Brown &opref->edata[i + qf->numinputfields]); CeedChk(ierr); 234668048e2SJed Brown } 235668048e2SJed Brown } else { 236885ac19cSjeremylt // Restriction 237885ac19cSjeremylt ierr = CeedVectorGetArray(opref->evecs[ieout], CEED_MEM_HOST, 238885ac19cSjeremylt &opref->edata[i + qf->numinputfields]); CeedChk(ierr); 239885ac19cSjeremylt ieout++; 240885ac19cSjeremylt } 241885ac19cSjeremylt } 242885ac19cSjeremylt 243885ac19cSjeremylt // Loop through elements 244885ac19cSjeremylt for (CeedInt e=0; e<op->numelements; e++) { 245885ac19cSjeremylt // Input basis apply if needed 246885ac19cSjeremylt for (CeedInt i=0; i<qf->numinputfields; i++) { 247885ac19cSjeremylt // Get elemsize 248668048e2SJed Brown if (op->inputfields[i].Erestrict != CEED_RESTRICTION_IDENTITY) { 249885ac19cSjeremylt elemsize = op->inputfields[i].Erestrict->elemsize; 250885ac19cSjeremylt } else { 251885ac19cSjeremylt elemsize = Q; 252885ac19cSjeremylt } 253885ac19cSjeremylt // Get emode, ncomp 254885ac19cSjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 255885ac19cSjeremylt CeedInt ncomp = qf->inputfields[i].ncomp; 256885ac19cSjeremylt // Basis action 257885ac19cSjeremylt switch(emode) { 258885ac19cSjeremylt case CEED_EVAL_NONE: 259885ac19cSjeremylt opref->indata[i] = &opref->edata[i][e*Q*ncomp]; 260885ac19cSjeremylt break; 261885ac19cSjeremylt case CEED_EVAL_INTERP: 262d3181881Sjeremylt ierr = CeedBasisApply(op->inputfields[i].basis, 1, CEED_NOTRANSPOSE, 263885ac19cSjeremylt CEED_EVAL_INTERP, &opref->edata[i][e*elemsize*ncomp], opref->qdata[i]); 264885ac19cSjeremylt CeedChk(ierr); 265885ac19cSjeremylt opref->indata[i] = opref->qdata[i]; 266885ac19cSjeremylt break; 267885ac19cSjeremylt case CEED_EVAL_GRAD: 268d3181881Sjeremylt ierr = CeedBasisApply(op->inputfields[i].basis, 1, CEED_NOTRANSPOSE, 269885ac19cSjeremylt CEED_EVAL_GRAD, &opref->edata[i][e*elemsize*ncomp], opref->qdata[i]); 270885ac19cSjeremylt CeedChk(ierr); 271885ac19cSjeremylt opref->indata[i] = opref->qdata[i]; 272885ac19cSjeremylt break; 273885ac19cSjeremylt case CEED_EVAL_WEIGHT: 274885ac19cSjeremylt break; // No action 275885ac19cSjeremylt case CEED_EVAL_DIV: 276885ac19cSjeremylt break; // Not implimented 277885ac19cSjeremylt case CEED_EVAL_CURL: 278885ac19cSjeremylt break; // Not implimented 279885ac19cSjeremylt } 280885ac19cSjeremylt } 281885ac19cSjeremylt // Output pointers 282885ac19cSjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 283885ac19cSjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 284885ac19cSjeremylt if (emode == CEED_EVAL_NONE) { 285885ac19cSjeremylt CeedInt ncomp = qf->outputfields[i].ncomp; 286885ac19cSjeremylt opref->outdata[i] = &opref->edata[i + qf->numinputfields][e*Q*ncomp]; 287885ac19cSjeremylt } 288885ac19cSjeremylt } 289885ac19cSjeremylt // Q function 290885ac19cSjeremylt ierr = CeedQFunctionApply(op->qf, Q, (const CeedScalar * const*) opref->indata, 291885ac19cSjeremylt opref->outdata); CeedChk(ierr); 292885ac19cSjeremylt 293885ac19cSjeremylt // Output basis apply if needed 294885ac19cSjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 295885ac19cSjeremylt // Get elemsize 296668048e2SJed Brown if (op->outputfields[i].Erestrict != CEED_RESTRICTION_IDENTITY) { 297885ac19cSjeremylt elemsize = op->outputfields[i].Erestrict->elemsize; 298885ac19cSjeremylt } else { 299885ac19cSjeremylt elemsize = Q; 300885ac19cSjeremylt } 301885ac19cSjeremylt // Get emode, ncomp 302885ac19cSjeremylt CeedInt ncomp = qf->outputfields[i].ncomp; 303885ac19cSjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 304885ac19cSjeremylt // Basis action 305885ac19cSjeremylt switch(emode) { 306885ac19cSjeremylt case CEED_EVAL_NONE: 307885ac19cSjeremylt break; // No action 308885ac19cSjeremylt case CEED_EVAL_INTERP: 309d3181881Sjeremylt ierr = CeedBasisApply(op->outputfields[i].basis, 1, CEED_TRANSPOSE, 310885ac19cSjeremylt CEED_EVAL_INTERP, opref->outdata[i], 311885ac19cSjeremylt &opref->edata[i + qf->numinputfields][e*elemsize*ncomp]); CeedChk(ierr); 312885ac19cSjeremylt break; 313885ac19cSjeremylt case CEED_EVAL_GRAD: 314*0c7a96bbSjeremylt ierr = CeedBasisApply(op->outputfields[i].basis, 1, CEED_TRANSPOSE, 315*0c7a96bbSjeremylt CEED_EVAL_GRAD, 316885ac19cSjeremylt opref->outdata[i], &opref->edata[i + qf->numinputfields][e*elemsize*ncomp]); 317885ac19cSjeremylt CeedChk(ierr); 318885ac19cSjeremylt break; 319885ac19cSjeremylt case CEED_EVAL_WEIGHT: 320885ac19cSjeremylt break; // Should not occur 321885ac19cSjeremylt case CEED_EVAL_DIV: 322885ac19cSjeremylt break; // Not implimented 323885ac19cSjeremylt case CEED_EVAL_CURL: 324885ac19cSjeremylt break; // Not implimented 325885ac19cSjeremylt } 326885ac19cSjeremylt } 327885ac19cSjeremylt } 328885ac19cSjeremylt 329885ac19cSjeremylt // Output restriction 330885ac19cSjeremylt for (CeedInt i=0,ieout=opref->numein; i<qf->numoutputfields; i++) { 331668048e2SJed Brown // No Restriction 332668048e2SJed Brown if (op->outputfields[i].Erestrict == CEED_RESTRICTION_IDENTITY) { 333885ac19cSjeremylt // Active 334668048e2SJed Brown if (op->outputfields[i].vec == CEED_VECTOR_ACTIVE) { 335668048e2SJed Brown ierr = CeedVectorRestoreArray(outvec, &opref->edata[i + qf->numinputfields]); 336668048e2SJed Brown CeedChk(ierr); 337668048e2SJed Brown } else { 338668048e2SJed Brown // Passive 339668048e2SJed Brown ierr = CeedVectorRestoreArray(op->outputfields[i].vec, 340668048e2SJed Brown &opref->edata[i + qf->numinputfields]); CeedChk(ierr); 341668048e2SJed Brown } 342668048e2SJed Brown } else { 343668048e2SJed Brown // Restriction 344668048e2SJed Brown // Active 345668048e2SJed Brown if (op->outputfields[i].vec == CEED_VECTOR_ACTIVE) { 3467ca8db16Sjeremylt // Restore evec 347885ac19cSjeremylt ierr = CeedVectorRestoreArray(opref->evecs[ieout], 348885ac19cSjeremylt &opref->edata[i + qf->numinputfields]); CeedChk(ierr); 3497ca8db16Sjeremylt // Zero lvec 3507ca8db16Sjeremylt ierr = CeedVectorGetArray(outvec, CEED_MEM_HOST, &vec_temp); CeedChk(ierr); 3517ca8db16Sjeremylt for (CeedInt j=0; j<outvec->length; j++) 3527ca8db16Sjeremylt vec_temp[j] = 0.; 3537ca8db16Sjeremylt ierr = CeedVectorRestoreArray(outvec, &vec_temp); CeedChk(ierr); 3547ca8db16Sjeremylt // Restrict 355885ac19cSjeremylt ierr = CeedElemRestrictionApply(op->outputfields[i].Erestrict, CEED_TRANSPOSE, 356885ac19cSjeremylt lmode, opref->evecs[ieout], outvec, request); CeedChk(ierr); 357885ac19cSjeremylt ieout++; 358885ac19cSjeremylt } else { 359885ac19cSjeremylt // Passive 360668048e2SJed Brown // Restore evec 361668048e2SJed Brown ierr = CeedVectorRestoreArray(opref->evecs[ieout], 362885ac19cSjeremylt &opref->edata[i + qf->numinputfields]); CeedChk(ierr); 363668048e2SJed Brown // Zero lvec 364668048e2SJed Brown ierr = CeedVectorGetArray(op->outputfields[i].vec, CEED_MEM_HOST, &vec_temp); 365885ac19cSjeremylt CeedChk(ierr); 366668048e2SJed Brown for (CeedInt j=0; j<op->outputfields[i].vec->length; j++) 367668048e2SJed Brown vec_temp[j] = 0.; 368668048e2SJed Brown ierr = CeedVectorRestoreArray(op->outputfields[i].vec, &vec_temp); 369668048e2SJed Brown CeedChk(ierr); 370668048e2SJed Brown // Restrict 371668048e2SJed Brown ierr = CeedElemRestrictionApply(op->outputfields[i].Erestrict, CEED_TRANSPOSE, 372668048e2SJed Brown lmode, opref->evecs[ieout], op->outputfields[i].vec, 373668048e2SJed Brown request); CeedChk(ierr); 374668048e2SJed Brown ieout++; 375885ac19cSjeremylt } 376885ac19cSjeremylt } 377885ac19cSjeremylt } 378885ac19cSjeremylt 3797ca8db16Sjeremylt // Restore input arrays 3807ca8db16Sjeremylt for (CeedInt i=0,iein=0; i<qf->numinputfields; i++) { 381668048e2SJed Brown // No Restriction 382668048e2SJed Brown if (op->inputfields[i].Erestrict == CEED_RESTRICTION_IDENTITY) { 3837ca8db16Sjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 3847ca8db16Sjeremylt if (emode & CEED_EVAL_WEIGHT) { 3857ca8db16Sjeremylt } else { 3867ca8db16Sjeremylt // Active 387668048e2SJed Brown if (op->inputfields[i].vec == CEED_VECTOR_ACTIVE) { 3887ca8db16Sjeremylt ierr = CeedVectorRestoreArrayRead(invec, 3897ca8db16Sjeremylt (const CeedScalar **) &opref->edata[i]); CeedChk(ierr); 390668048e2SJed Brown // Passive 391668048e2SJed Brown } else { 392668048e2SJed Brown ierr = CeedVectorRestoreArrayRead(op->inputfields[i].vec, 393668048e2SJed Brown (const CeedScalar **) &opref->edata[i]); CeedChk(ierr); 3947ca8db16Sjeremylt } 3957ca8db16Sjeremylt } 396668048e2SJed Brown } else { 397668048e2SJed Brown // Restriction 398668048e2SJed Brown ierr = CeedVectorRestoreArrayRead(opref->evecs[iein], 399668048e2SJed Brown (const CeedScalar **) &opref->edata[i]); CeedChk(ierr); 400668048e2SJed Brown iein++; 4017ca8db16Sjeremylt } 4027ca8db16Sjeremylt } 4037ca8db16Sjeremylt 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