1*4a2e7687Sjeremylt // Copyright (c) 2017-2018, Lawrence Livermore National Security, LLC. 2*4a2e7687Sjeremylt // Produced at the Lawrence Livermore National Laboratory. LLNL-CODE-734707. 3*4a2e7687Sjeremylt // All Rights reserved. See files LICENSE and NOTICE for details. 4*4a2e7687Sjeremylt // 5*4a2e7687Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software 6*4a2e7687Sjeremylt // libraries and APIs for efficient high-order finite element and spectral 7*4a2e7687Sjeremylt // element discretizations for exascale applications. For more information and 8*4a2e7687Sjeremylt // source code availability see http://github.com/ceed. 9*4a2e7687Sjeremylt // 10*4a2e7687Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11*4a2e7687Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office 12*4a2e7687Sjeremylt // of Science and the National Nuclear Security Administration) responsible for 13*4a2e7687Sjeremylt // the planning and preparation of a capable exascale ecosystem, including 14*4a2e7687Sjeremylt // software, applications, hardware, advanced system engineering and early 15*4a2e7687Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative. 16*4a2e7687Sjeremylt 17*4a2e7687Sjeremylt #include <ceed-impl.h> 18*4a2e7687Sjeremylt #include <string.h> 19*4a2e7687Sjeremylt #include "ceed-blocked.h" 20*4a2e7687Sjeremylt #include "../ref/ceed-ref.h" 21*4a2e7687Sjeremylt 22*4a2e7687Sjeremylt static int CeedOperatorDestroy_Blocked(CeedOperator op) { 23*4a2e7687Sjeremylt CeedOperator_Blocked *impl = op->data; 24*4a2e7687Sjeremylt int ierr; 25*4a2e7687Sjeremylt 26*4a2e7687Sjeremylt for (CeedInt i=0; i<impl->numein+impl->numeout; i++) { 27*4a2e7687Sjeremylt ierr = CeedElemRestrictionDestroy(&impl->blkrestr[i]); CeedChk(ierr); 28*4a2e7687Sjeremylt ierr = CeedVectorDestroy(&impl->evecs[i]); CeedChk(ierr); 29*4a2e7687Sjeremylt } 30*4a2e7687Sjeremylt ierr = CeedFree(&impl->blkrestr); CeedChk(ierr); 31*4a2e7687Sjeremylt ierr = CeedFree(&impl->evecs); CeedChk(ierr); 32*4a2e7687Sjeremylt ierr = CeedFree(&impl->edata); CeedChk(ierr); 33*4a2e7687Sjeremylt 34*4a2e7687Sjeremylt for (CeedInt i=0; i<impl->numqin+impl->numqout; i++) { 35*4a2e7687Sjeremylt ierr = CeedFree(&impl->qdata_alloc[i]); CeedChk(ierr); 36*4a2e7687Sjeremylt } 37*4a2e7687Sjeremylt ierr = CeedFree(&impl->qdata_alloc); CeedChk(ierr); 38*4a2e7687Sjeremylt ierr = CeedFree(&impl->qdata); CeedChk(ierr); 39*4a2e7687Sjeremylt 40*4a2e7687Sjeremylt ierr = CeedFree(&impl->indata); CeedChk(ierr); 41*4a2e7687Sjeremylt ierr = CeedFree(&impl->outdata); CeedChk(ierr); 42*4a2e7687Sjeremylt 43*4a2e7687Sjeremylt ierr = CeedFree(&op->data); CeedChk(ierr); 44*4a2e7687Sjeremylt return 0; 45*4a2e7687Sjeremylt } 46*4a2e7687Sjeremylt 47*4a2e7687Sjeremylt /* 48*4a2e7687Sjeremylt Setup infields or outfields 49*4a2e7687Sjeremylt */ 50*4a2e7687Sjeremylt static int CeedOperatorSetupFields_Blocked(struct CeedQFunctionField qfields[16], 51*4a2e7687Sjeremylt struct CeedOperatorField ofields[16], 52*4a2e7687Sjeremylt CeedElemRestriction *blkrestr, 53*4a2e7687Sjeremylt CeedVector *evecs, CeedScalar **qdata, 54*4a2e7687Sjeremylt CeedScalar **qdata_alloc, CeedScalar **indata, 55*4a2e7687Sjeremylt CeedInt starti, CeedInt startq, 56*4a2e7687Sjeremylt CeedInt numfields, CeedInt Q) { 57*4a2e7687Sjeremylt CeedInt dim, ierr, iq=startq, ncomp; 58*4a2e7687Sjeremylt const CeedInt blksize = 8; 59*4a2e7687Sjeremylt 60*4a2e7687Sjeremylt // Loop over fields 61*4a2e7687Sjeremylt for (CeedInt i=0; i<numfields; i++) { 62*4a2e7687Sjeremylt CeedEvalMode emode = qfields[i].emode; 63*4a2e7687Sjeremylt 64*4a2e7687Sjeremylt if (emode != CEED_EVAL_WEIGHT) { 65*4a2e7687Sjeremylt CeedElemRestriction r = ofields[i].Erestrict; 66*4a2e7687Sjeremylt CeedElemRestriction_Ref *data = r->data; 67*4a2e7687Sjeremylt ierr = CeedElemRestrictionCreateBlocked(r->ceed, r->nelem, r->elemsize, 68*4a2e7687Sjeremylt blksize, r->ndof, r->ncomp, 69*4a2e7687Sjeremylt CEED_MEM_HOST, CEED_COPY_VALUES, 70*4a2e7687Sjeremylt data->indices, &blkrestr[i+starti]); 71*4a2e7687Sjeremylt CeedChk(ierr); 72*4a2e7687Sjeremylt ierr = CeedElemRestrictionCreateVector(blkrestr[i+starti], NULL, 73*4a2e7687Sjeremylt &evecs[i+starti]); 74*4a2e7687Sjeremylt CeedChk(ierr); 75*4a2e7687Sjeremylt } 76*4a2e7687Sjeremylt 77*4a2e7687Sjeremylt switch(emode) { 78*4a2e7687Sjeremylt case CEED_EVAL_NONE: 79*4a2e7687Sjeremylt break; // No action 80*4a2e7687Sjeremylt case CEED_EVAL_INTERP: 81*4a2e7687Sjeremylt ncomp = qfields[i].ncomp; 82*4a2e7687Sjeremylt ierr = CeedMalloc(Q*ncomp*blksize, &qdata_alloc[iq]); CeedChk(ierr); 83*4a2e7687Sjeremylt qdata[i + starti] = qdata_alloc[iq]; 84*4a2e7687Sjeremylt iq++; 85*4a2e7687Sjeremylt break; 86*4a2e7687Sjeremylt case CEED_EVAL_GRAD: 87*4a2e7687Sjeremylt ncomp = qfields[i].ncomp; 88*4a2e7687Sjeremylt dim = ofields[i].basis->dim; 89*4a2e7687Sjeremylt ierr = CeedMalloc(Q*ncomp*dim*blksize, &qdata_alloc[iq]); CeedChk(ierr); 90*4a2e7687Sjeremylt qdata[i + starti] = qdata_alloc[iq]; 91*4a2e7687Sjeremylt iq++; 92*4a2e7687Sjeremylt break; 93*4a2e7687Sjeremylt case CEED_EVAL_WEIGHT: // Only on input fields 94*4a2e7687Sjeremylt ierr = CeedMalloc(Q*blksize, &qdata_alloc[iq]); CeedChk(ierr); 95*4a2e7687Sjeremylt ierr = CeedBasisApply(ofields[iq].basis, blksize, CEED_NOTRANSPOSE, 96*4a2e7687Sjeremylt CEED_EVAL_WEIGHT, NULL, qdata_alloc[iq]); CeedChk(ierr); 97*4a2e7687Sjeremylt qdata[i] = qdata_alloc[iq]; 98*4a2e7687Sjeremylt indata[i] = qdata[i]; 99*4a2e7687Sjeremylt iq++; 100*4a2e7687Sjeremylt break; 101*4a2e7687Sjeremylt case CEED_EVAL_DIV: 102*4a2e7687Sjeremylt break; // Not implimented 103*4a2e7687Sjeremylt case CEED_EVAL_CURL: 104*4a2e7687Sjeremylt break; // Not implimented 105*4a2e7687Sjeremylt } 106*4a2e7687Sjeremylt } 107*4a2e7687Sjeremylt return 0; 108*4a2e7687Sjeremylt } 109*4a2e7687Sjeremylt 110*4a2e7687Sjeremylt /* 111*4a2e7687Sjeremylt CeedOperator needs to connect all the named fields (be they active or passive) 112*4a2e7687Sjeremylt to the named inputs and outputs of its CeedQFunction. 113*4a2e7687Sjeremylt */ 114*4a2e7687Sjeremylt static int CeedOperatorSetup_Blocked(CeedOperator op) { 115*4a2e7687Sjeremylt if (op->setupdone) return 0; 116*4a2e7687Sjeremylt CeedOperator_Blocked *impl = op->data; 117*4a2e7687Sjeremylt CeedQFunction qf = op->qf; 118*4a2e7687Sjeremylt CeedInt Q = op->numqpoints, numinputfields, numoutputfields; 119*4a2e7687Sjeremylt int ierr; 120*4a2e7687Sjeremylt 121*4a2e7687Sjeremylt // Count infield and outfield array sizes and evectors 122*4a2e7687Sjeremylt ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 123*4a2e7687Sjeremylt CeedChk(ierr); 124*4a2e7687Sjeremylt impl->numein = numinputfields; 125*4a2e7687Sjeremylt for (CeedInt i=0; i<numinputfields; i++) { 126*4a2e7687Sjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 127*4a2e7687Sjeremylt impl->numqin += !!(emode & CEED_EVAL_INTERP) + !!(emode & CEED_EVAL_GRAD) + 128*4a2e7687Sjeremylt !!(emode & CEED_EVAL_WEIGHT); 129*4a2e7687Sjeremylt } 130*4a2e7687Sjeremylt impl->numeout = numoutputfields; 131*4a2e7687Sjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 132*4a2e7687Sjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 133*4a2e7687Sjeremylt impl->numqout += !!(emode & CEED_EVAL_INTERP) + !!(emode & CEED_EVAL_GRAD); 134*4a2e7687Sjeremylt } 135*4a2e7687Sjeremylt 136*4a2e7687Sjeremylt // Allocate 137*4a2e7687Sjeremylt ierr = CeedCalloc(impl->numein + impl->numeout, &impl->blkrestr); 138*4a2e7687Sjeremylt CeedChk(ierr); 139*4a2e7687Sjeremylt ierr = CeedCalloc(impl->numein + impl->numeout, &impl->evecs); 140*4a2e7687Sjeremylt CeedChk(ierr); 141*4a2e7687Sjeremylt ierr = CeedCalloc(impl->numein + impl->numeout, &impl->edata); 142*4a2e7687Sjeremylt CeedChk(ierr); 143*4a2e7687Sjeremylt 144*4a2e7687Sjeremylt ierr = CeedCalloc(impl->numqin + impl->numqout, &impl->qdata_alloc); 145*4a2e7687Sjeremylt CeedChk(ierr); 146*4a2e7687Sjeremylt ierr = CeedCalloc(numinputfields + numoutputfields, &impl->qdata); 147*4a2e7687Sjeremylt CeedChk(ierr); 148*4a2e7687Sjeremylt 149*4a2e7687Sjeremylt ierr = CeedCalloc(16, &impl->indata); CeedChk(ierr); 150*4a2e7687Sjeremylt ierr = CeedCalloc(16, &impl->outdata); CeedChk(ierr); 151*4a2e7687Sjeremylt // Set up infield and outfield pointer arrays 152*4a2e7687Sjeremylt // Infields 153*4a2e7687Sjeremylt ierr = CeedOperatorSetupFields_Blocked(qf->inputfields, op->inputfields, 154*4a2e7687Sjeremylt impl->blkrestr, impl->evecs, 155*4a2e7687Sjeremylt impl->qdata, impl->qdata_alloc, 156*4a2e7687Sjeremylt impl->indata, 0, 157*4a2e7687Sjeremylt 0, numinputfields, Q); 158*4a2e7687Sjeremylt CeedChk(ierr); 159*4a2e7687Sjeremylt // Outfields 160*4a2e7687Sjeremylt ierr = CeedOperatorSetupFields_Blocked(qf->outputfields, op->outputfields, 161*4a2e7687Sjeremylt impl->blkrestr, impl->evecs, 162*4a2e7687Sjeremylt impl->qdata, impl->qdata_alloc, 163*4a2e7687Sjeremylt impl->indata, numinputfields, 164*4a2e7687Sjeremylt impl->numqin, numoutputfields, Q); 165*4a2e7687Sjeremylt CeedChk(ierr); 166*4a2e7687Sjeremylt // Input Qvecs 167*4a2e7687Sjeremylt for (CeedInt i=0; i<numinputfields; i++) { 168*4a2e7687Sjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 169*4a2e7687Sjeremylt if ((emode != CEED_EVAL_NONE) && (emode != CEED_EVAL_WEIGHT)) 170*4a2e7687Sjeremylt impl->indata[i] = impl->qdata[i]; 171*4a2e7687Sjeremylt } 172*4a2e7687Sjeremylt // Output Qvecs 173*4a2e7687Sjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 174*4a2e7687Sjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 175*4a2e7687Sjeremylt if (emode != CEED_EVAL_NONE) 176*4a2e7687Sjeremylt impl->outdata[i] = impl->qdata[i + numinputfields]; 177*4a2e7687Sjeremylt } 178*4a2e7687Sjeremylt 179*4a2e7687Sjeremylt op->setupdone = 1; 180*4a2e7687Sjeremylt 181*4a2e7687Sjeremylt return 0; 182*4a2e7687Sjeremylt } 183*4a2e7687Sjeremylt 184*4a2e7687Sjeremylt static int CeedOperatorApply_Blocked(CeedOperator op, CeedVector invec, 185*4a2e7687Sjeremylt CeedVector outvec, CeedRequest *request) { 186*4a2e7687Sjeremylt CeedOperator_Blocked *impl = op->data; 187*4a2e7687Sjeremylt const CeedInt blksize = 8; 188*4a2e7687Sjeremylt CeedInt Q = op->numqpoints, elemsize, numinputfields, numoutputfields, 189*4a2e7687Sjeremylt nblks = (op->numelements/blksize) + !!(op->numelements%blksize); 190*4a2e7687Sjeremylt int ierr; 191*4a2e7687Sjeremylt CeedQFunction qf = op->qf; 192*4a2e7687Sjeremylt CeedTransposeMode lmode = CEED_NOTRANSPOSE; 193*4a2e7687Sjeremylt 194*4a2e7687Sjeremylt // Setup 195*4a2e7687Sjeremylt ierr = CeedOperatorSetup_Blocked(op); CeedChk(ierr); 196*4a2e7687Sjeremylt ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 197*4a2e7687Sjeremylt CeedChk(ierr); 198*4a2e7687Sjeremylt 199*4a2e7687Sjeremylt // Input Evecs and Restriction 200*4a2e7687Sjeremylt for (CeedInt i=0; i<numinputfields; i++) { 201*4a2e7687Sjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 202*4a2e7687Sjeremylt if (emode == CEED_EVAL_WEIGHT) { // Skip 203*4a2e7687Sjeremylt } else { 204*4a2e7687Sjeremylt // Active 205*4a2e7687Sjeremylt // Restrict 206*4a2e7687Sjeremylt if (op->inputfields[i].vec == CEED_VECTOR_ACTIVE) { 207*4a2e7687Sjeremylt ierr = CeedElemRestrictionApply(impl->blkrestr[i], CEED_NOTRANSPOSE, 208*4a2e7687Sjeremylt lmode, invec, impl->evecs[i], 209*4a2e7687Sjeremylt request); CeedChk(ierr); CeedChk(ierr); 210*4a2e7687Sjeremylt } else { 211*4a2e7687Sjeremylt // Passive 212*4a2e7687Sjeremylt // Restrict 213*4a2e7687Sjeremylt ierr = CeedElemRestrictionApply(impl->blkrestr[i], CEED_NOTRANSPOSE, 214*4a2e7687Sjeremylt lmode, op->inputfields[i].vec, impl->evecs[i], 215*4a2e7687Sjeremylt request); CeedChk(ierr); 216*4a2e7687Sjeremylt } 217*4a2e7687Sjeremylt // Get evec 218*4a2e7687Sjeremylt ierr = CeedVectorGetArrayRead(impl->evecs[i], CEED_MEM_HOST, 219*4a2e7687Sjeremylt (const CeedScalar **) &impl->edata[i]); 220*4a2e7687Sjeremylt CeedChk(ierr); 221*4a2e7687Sjeremylt } 222*4a2e7687Sjeremylt } 223*4a2e7687Sjeremylt 224*4a2e7687Sjeremylt // Output Evecs 225*4a2e7687Sjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 226*4a2e7687Sjeremylt ierr = CeedVectorGetArray(impl->evecs[i+impl->numein], CEED_MEM_HOST, 227*4a2e7687Sjeremylt &impl->edata[i + numinputfields]); CeedChk(ierr); 228*4a2e7687Sjeremylt } 229*4a2e7687Sjeremylt 230*4a2e7687Sjeremylt // Loop through elements 231*4a2e7687Sjeremylt for (CeedInt e=0; e<nblks*blksize; e+=blksize) { 232*4a2e7687Sjeremylt // Input basis apply if needed 233*4a2e7687Sjeremylt for (CeedInt i=0; i<numinputfields; i++) { 234*4a2e7687Sjeremylt // Get elemsize, emode, ncomp 235*4a2e7687Sjeremylt elemsize = op->inputfields[i].Erestrict->elemsize; 236*4a2e7687Sjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 237*4a2e7687Sjeremylt CeedInt ncomp = qf->inputfields[i].ncomp; 238*4a2e7687Sjeremylt // Basis action 239*4a2e7687Sjeremylt switch(emode) { 240*4a2e7687Sjeremylt case CEED_EVAL_NONE: 241*4a2e7687Sjeremylt impl->indata[i] = &impl->edata[i][e*Q*ncomp]; 242*4a2e7687Sjeremylt break; 243*4a2e7687Sjeremylt case CEED_EVAL_INTERP: 244*4a2e7687Sjeremylt ierr = CeedBasisApply(op->inputfields[i].basis, blksize, CEED_NOTRANSPOSE, 245*4a2e7687Sjeremylt CEED_EVAL_INTERP, &impl->edata[i][e*elemsize*ncomp], impl->qdata[i]); 246*4a2e7687Sjeremylt CeedChk(ierr); 247*4a2e7687Sjeremylt break; 248*4a2e7687Sjeremylt case CEED_EVAL_GRAD: 249*4a2e7687Sjeremylt ierr = CeedBasisApply(op->inputfields[i].basis, blksize, CEED_NOTRANSPOSE, 250*4a2e7687Sjeremylt CEED_EVAL_GRAD, &impl->edata[i][e*elemsize*ncomp], impl->qdata[i]); 251*4a2e7687Sjeremylt CeedChk(ierr); 252*4a2e7687Sjeremylt break; 253*4a2e7687Sjeremylt case CEED_EVAL_WEIGHT: 254*4a2e7687Sjeremylt break; // No action 255*4a2e7687Sjeremylt case CEED_EVAL_DIV: 256*4a2e7687Sjeremylt break; // Not implimented 257*4a2e7687Sjeremylt case CEED_EVAL_CURL: 258*4a2e7687Sjeremylt break; // Not implimented 259*4a2e7687Sjeremylt } 260*4a2e7687Sjeremylt } 261*4a2e7687Sjeremylt 262*4a2e7687Sjeremylt // Output pointers 263*4a2e7687Sjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 264*4a2e7687Sjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 265*4a2e7687Sjeremylt if (emode == CEED_EVAL_NONE) { 266*4a2e7687Sjeremylt CeedInt ncomp = qf->outputfields[i].ncomp; 267*4a2e7687Sjeremylt impl->outdata[i] = &impl->edata[i + numinputfields][e*Q*ncomp]; 268*4a2e7687Sjeremylt } 269*4a2e7687Sjeremylt } 270*4a2e7687Sjeremylt // Q function 271*4a2e7687Sjeremylt ierr = CeedQFunctionApply(op->qf, Q*blksize, 272*4a2e7687Sjeremylt (const CeedScalar * const*) impl->indata, 273*4a2e7687Sjeremylt impl->outdata); CeedChk(ierr); 274*4a2e7687Sjeremylt 275*4a2e7687Sjeremylt // Output basis apply if needed 276*4a2e7687Sjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 277*4a2e7687Sjeremylt // Get elemsize, emode, ncomp 278*4a2e7687Sjeremylt elemsize = op->outputfields[i].Erestrict->elemsize; 279*4a2e7687Sjeremylt CeedInt ncomp = qf->outputfields[i].ncomp; 280*4a2e7687Sjeremylt CeedEvalMode emode = qf->outputfields[i].emode; 281*4a2e7687Sjeremylt // Basis action 282*4a2e7687Sjeremylt switch(emode) { 283*4a2e7687Sjeremylt case CEED_EVAL_NONE: 284*4a2e7687Sjeremylt break; // No action 285*4a2e7687Sjeremylt case CEED_EVAL_INTERP: 286*4a2e7687Sjeremylt ierr = CeedBasisApply(op->outputfields[i].basis, blksize, CEED_TRANSPOSE, 287*4a2e7687Sjeremylt CEED_EVAL_INTERP, impl->outdata[i], 288*4a2e7687Sjeremylt &impl->edata[i + numinputfields][e*elemsize*ncomp]); 289*4a2e7687Sjeremylt CeedChk(ierr); 290*4a2e7687Sjeremylt break; 291*4a2e7687Sjeremylt case CEED_EVAL_GRAD: 292*4a2e7687Sjeremylt ierr = CeedBasisApply(op->outputfields[i].basis, blksize, CEED_TRANSPOSE, 293*4a2e7687Sjeremylt CEED_EVAL_GRAD, 294*4a2e7687Sjeremylt impl->outdata[i], &impl->edata[i + numinputfields][e*elemsize*ncomp]); 295*4a2e7687Sjeremylt CeedChk(ierr); 296*4a2e7687Sjeremylt break; 297*4a2e7687Sjeremylt case CEED_EVAL_WEIGHT: 298*4a2e7687Sjeremylt return CeedError(op->ceed, 1, 299*4a2e7687Sjeremylt "CEED_EVAL_WEIGHT cannot be an output evaluation mode"); 300*4a2e7687Sjeremylt break; // Should not occur 301*4a2e7687Sjeremylt case CEED_EVAL_DIV: 302*4a2e7687Sjeremylt break; // Not implimented 303*4a2e7687Sjeremylt case CEED_EVAL_CURL: 304*4a2e7687Sjeremylt break; // Not implimented 305*4a2e7687Sjeremylt } 306*4a2e7687Sjeremylt } 307*4a2e7687Sjeremylt } 308*4a2e7687Sjeremylt 309*4a2e7687Sjeremylt // Zero lvecs 310*4a2e7687Sjeremylt ierr = CeedVectorSetValue(outvec, 0.0); CeedChk(ierr); 311*4a2e7687Sjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) 312*4a2e7687Sjeremylt if (op->outputfields[i].vec != CEED_VECTOR_ACTIVE) { 313*4a2e7687Sjeremylt ierr = CeedVectorSetValue(op->outputfields[i].vec, 0.0); CeedChk(ierr); 314*4a2e7687Sjeremylt } 315*4a2e7687Sjeremylt 316*4a2e7687Sjeremylt // Output restriction 317*4a2e7687Sjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 318*4a2e7687Sjeremylt // Restore evec 319*4a2e7687Sjeremylt ierr = CeedVectorRestoreArray(impl->evecs[i+impl->numein], 320*4a2e7687Sjeremylt &impl->edata[i + numinputfields]); CeedChk(ierr); 321*4a2e7687Sjeremylt // Active 322*4a2e7687Sjeremylt if (op->outputfields[i].vec == CEED_VECTOR_ACTIVE) { 323*4a2e7687Sjeremylt // Restrict 324*4a2e7687Sjeremylt ierr = CeedElemRestrictionApply(impl->blkrestr[i+impl->numein], CEED_TRANSPOSE, 325*4a2e7687Sjeremylt lmode, impl->evecs[i+impl->numein], outvec, request); CeedChk(ierr); 326*4a2e7687Sjeremylt } else { 327*4a2e7687Sjeremylt // Passive 328*4a2e7687Sjeremylt // Restrict 329*4a2e7687Sjeremylt ierr = CeedElemRestrictionApply(impl->blkrestr[i+impl->numein], CEED_TRANSPOSE, 330*4a2e7687Sjeremylt lmode, impl->evecs[i+impl->numein], op->outputfields[i].vec, 331*4a2e7687Sjeremylt request); CeedChk(ierr); 332*4a2e7687Sjeremylt } 333*4a2e7687Sjeremylt } 334*4a2e7687Sjeremylt 335*4a2e7687Sjeremylt // Restore input arrays 336*4a2e7687Sjeremylt for (CeedInt i=0; i<numinputfields; i++) { 337*4a2e7687Sjeremylt CeedEvalMode emode = qf->inputfields[i].emode; 338*4a2e7687Sjeremylt if (emode == CEED_EVAL_WEIGHT) { // Skip 339*4a2e7687Sjeremylt } else { 340*4a2e7687Sjeremylt ierr = CeedVectorRestoreArrayRead(impl->evecs[i], 341*4a2e7687Sjeremylt (const CeedScalar **) &impl->edata[i]); CeedChk(ierr); 342*4a2e7687Sjeremylt } 343*4a2e7687Sjeremylt } 344*4a2e7687Sjeremylt 345*4a2e7687Sjeremylt return 0; 346*4a2e7687Sjeremylt } 347*4a2e7687Sjeremylt 348*4a2e7687Sjeremylt int CeedOperatorCreate_Blocked(CeedOperator op) { 349*4a2e7687Sjeremylt CeedOperator_Blocked *impl; 350*4a2e7687Sjeremylt int ierr; 351*4a2e7687Sjeremylt 352*4a2e7687Sjeremylt ierr = CeedCalloc(1, &impl); CeedChk(ierr); 353*4a2e7687Sjeremylt op->data = impl; 354*4a2e7687Sjeremylt op->Destroy = CeedOperatorDestroy_Blocked; 355*4a2e7687Sjeremylt op->Apply = CeedOperatorApply_Blocked; 356*4a2e7687Sjeremylt return 0; 357*4a2e7687Sjeremylt } 358