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-ref.h" 1821617c04Sjeremylt 19d3181881Sjeremylt static int CeedBasisApply_Ref(CeedBasis basis, CeedInt nelem, 20d3181881Sjeremylt CeedTransposeMode tmode, CeedEvalMode emode, 21aedaa0e5Sjeremylt CeedVector U, CeedVector V) { 2221617c04Sjeremylt int ierr; 234ce2993fSjeremylt Ceed ceed; 244ce2993fSjeremylt ierr = CeedBasisGetCeed(basis, &ceed); CeedChk(ierr); 258795c945Sjeremylt CeedInt dim, ncomp, nnodes, nqpt; 264ce2993fSjeremylt ierr = CeedBasisGetDimension(basis, &dim); CeedChk(ierr); 274ce2993fSjeremylt ierr = CeedBasisGetNumComponents(basis, &ncomp); CeedChk(ierr); 288795c945Sjeremylt ierr = CeedBasisGetNumNodes(basis, &nnodes); CeedChk(ierr); 294ce2993fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis, &nqpt); CeedChk(ierr); 302f86a920SJeremy L Thompson CeedTensorContract contract; 312f86a920SJeremy L Thompson ierr = CeedBasisGetTensorContract(basis, &contract); CeedChk(ierr); 3221617c04Sjeremylt const CeedInt add = (tmode == CEED_TRANSPOSE); 33aedaa0e5Sjeremylt const CeedScalar *u; 34aedaa0e5Sjeremylt CeedScalar *v; 35aedaa0e5Sjeremylt if (U) { 36aedaa0e5Sjeremylt ierr = CeedVectorGetArrayRead(U, CEED_MEM_HOST, &u); CeedChk(ierr); 37aedaa0e5Sjeremylt } else if (emode != CEED_EVAL_WEIGHT) { 38aedaa0e5Sjeremylt return CeedError(ceed, 1, 39aedaa0e5Sjeremylt "An input vector is required for this CeedEvalMode"); 40aedaa0e5Sjeremylt } 41aedaa0e5Sjeremylt ierr = CeedVectorGetArray(V, CEED_MEM_HOST, &v); CeedChk(ierr); 4221617c04Sjeremylt 438d94b059Sjeremylt // Clear v if operating in transpose 4421617c04Sjeremylt if (tmode == CEED_TRANSPOSE) { 458795c945Sjeremylt const CeedInt vsize = nelem*ncomp*nnodes; 4621617c04Sjeremylt for (CeedInt i = 0; i < vsize; i++) 4784a01de5SJeremy L Thompson v[i] = (CeedScalar) 0.0; 4821617c04Sjeremylt } 494ce2993fSjeremylt bool tensorbasis; 504ce2993fSjeremylt ierr = CeedBasisGetTensorStatus(basis, &tensorbasis); CeedChk(ierr); 5184a01de5SJeremy L Thompson // Tensor basis 524ce2993fSjeremylt if (tensorbasis) { 534ce2993fSjeremylt CeedInt P1d, Q1d; 544ce2993fSjeremylt ierr = CeedBasisGetNumNodes1D(basis, &P1d); CeedChk(ierr); 554ce2993fSjeremylt ierr = CeedBasisGetNumQuadraturePoints1D(basis, &Q1d); CeedChk(ierr); 56a2b73c81Sjeremylt switch (emode) { 578d94b059Sjeremylt // Interpolate to/from quadrature points 58a2b73c81Sjeremylt case CEED_EVAL_INTERP: { 59dfe03796SJeremy L Thompson CeedBasis_Ref *impl; 60dfe03796SJeremy L Thompson ierr = CeedBasisGetData(basis, (void *)&impl); CeedChk(ierr); 61dfe03796SJeremy L Thompson if (impl->collointerp) { 62dfe03796SJeremy L Thompson memcpy(v, u, nelem*ncomp*nnodes*sizeof(u[0])); 63dfe03796SJeremy L Thompson } else { 644ce2993fSjeremylt CeedInt P = P1d, Q = Q1d; 6521617c04Sjeremylt if (tmode == CEED_TRANSPOSE) { 664ce2993fSjeremylt P = Q1d; Q = P1d; 6721617c04Sjeremylt } 6884a01de5SJeremy L Thompson CeedInt pre = ncomp*CeedIntPow(P, dim-1), post = nelem; 6984a01de5SJeremy L Thompson CeedScalar tmp[2][nelem*ncomp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 704ce2993fSjeremylt CeedScalar *interp1d; 714ce2993fSjeremylt ierr = CeedBasisGetInterp(basis, &interp1d); CeedChk(ierr); 7221617c04Sjeremylt for (CeedInt d=0; d<dim; d++) { 732f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 7484a01de5SJeremy L Thompson interp1d, tmode, add&&(d==dim-1), 75dfe03796SJeremy L Thompson d==0?u:tmp[d%2], 76dfe03796SJeremy L Thompson d==dim-1?v:tmp[(d+1)%2]); 7721617c04Sjeremylt CeedChk(ierr); 7821617c04Sjeremylt pre /= P; 7921617c04Sjeremylt post *= Q; 8021617c04Sjeremylt } 81dfe03796SJeremy L Thompson } 82a2b73c81Sjeremylt } break; 838d94b059Sjeremylt // Evaluate the gradient to/from quadrature points 84a2b73c81Sjeremylt case CEED_EVAL_GRAD: { 8521617c04Sjeremylt // In CEED_NOTRANSPOSE mode: 86ecf6354eSJed Brown // u has shape [dim, ncomp, P^dim, nelem], row-major layout 87ecf6354eSJed Brown // v has shape [dim, ncomp, Q^dim, nelem], row-major layout 8821617c04Sjeremylt // In CEED_TRANSPOSE mode, the sizes of u and v are switched. 8984a01de5SJeremy L Thompson CeedInt P = P1d, Q = Q1d; 9021617c04Sjeremylt if (tmode == CEED_TRANSPOSE) { 9184a01de5SJeremy L Thompson P = Q1d, Q = Q1d; 9221617c04Sjeremylt } 9384a01de5SJeremy L Thompson CeedBasis_Ref *impl; 9484a01de5SJeremy L Thompson ierr = CeedBasisGetData(basis, (void *)&impl); CeedChk(ierr); 9584a01de5SJeremy L Thompson CeedInt pre = ncomp*CeedIntPow(P, dim-1), post = nelem; 9684a01de5SJeremy L Thompson CeedScalar *interp1d; 974ce2993fSjeremylt ierr = CeedBasisGetInterp(basis, &interp1d); CeedChk(ierr); 98dfe03796SJeremy L Thompson if (impl->collograd1d) { 99a7bd39daSjeremylt CeedScalar tmp[2][nelem*ncomp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 100a7bd39daSjeremylt CeedScalar interp[nelem*ncomp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 10184a01de5SJeremy L Thompson // Interpolate to quadrature points (NoTranspose) 10284a01de5SJeremy L Thompson // or Grad to quadrature points (Transpose) 10321617c04Sjeremylt for (CeedInt d=0; d<dim; d++) { 1042f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 10584a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 10684a01de5SJeremy L Thompson ? interp1d 107dfe03796SJeremy L Thompson : impl->collograd1d), 10884a01de5SJeremy L Thompson tmode, add&&(d>0), 10984a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 11084a01de5SJeremy L Thompson ? (d==0?u:tmp[d%2]) 11184a01de5SJeremy L Thompson : u + d*nqpt*ncomp*nelem), 11284a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 11384a01de5SJeremy L Thompson ? (d==dim-1?interp:tmp[(d+1)%2]) 11484a01de5SJeremy L Thompson : interp)); 11521617c04Sjeremylt CeedChk(ierr); 11621617c04Sjeremylt pre /= P; 11721617c04Sjeremylt post *= Q; 11821617c04Sjeremylt } 11984a01de5SJeremy L Thompson // Grad to quadrature points (NoTranspose) 1208795c945Sjeremylt // or Interpolate to nodes (Transpose) 12184a01de5SJeremy L Thompson P = Q1d, Q = Q1d; 12284a01de5SJeremy L Thompson if (tmode == CEED_TRANSPOSE) { 12384a01de5SJeremy L Thompson P = Q1d, Q = P1d; 12484a01de5SJeremy L Thompson } 12584a01de5SJeremy L Thompson pre = ncomp*CeedIntPow(P, dim-1), post = nelem; 12684a01de5SJeremy L Thompson for (CeedInt d=0; d<dim; d++) { 1272f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 12884a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 129dfe03796SJeremy L Thompson ? impl->collograd1d 13084a01de5SJeremy L Thompson : interp1d), 13184a01de5SJeremy L Thompson tmode, add&&(d==dim-1), 13284a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 13384a01de5SJeremy L Thompson ? interp 13484a01de5SJeremy L Thompson : (d==0?interp:tmp[d%2])), 13584a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 13684a01de5SJeremy L Thompson ? v + d*nqpt*ncomp*nelem 13784a01de5SJeremy L Thompson : (d==dim-1?v:tmp[(d+1)%2]))); 13884a01de5SJeremy L Thompson CeedChk(ierr); 13984a01de5SJeremy L Thompson pre /= P; 14084a01de5SJeremy L Thompson post *= Q; 14121617c04Sjeremylt } 142dfe03796SJeremy L Thompson } else if (impl->collointerp) { // Qpts collocated with nodes 143dfe03796SJeremy L Thompson CeedScalar *grad1d; 144dfe03796SJeremy L Thompson ierr = CeedBasisGetGrad(basis, &grad1d); CeedChk(ierr); 145dfe03796SJeremy L Thompson 146dfe03796SJeremy L Thompson // Dim contractions, identity in other directions 147dfe03796SJeremy L Thompson for (CeedInt d=0; d<dim; d++) { 148dfe03796SJeremy L Thompson CeedInt pre = ncomp*CeedIntPow(P, dim-1), post = nelem; 149dfe03796SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 150*a1dbd226Sjeremylt grad1d, tmode, add&&(d>0), 151dfe03796SJeremy L Thompson tmode == CEED_NOTRANSPOSE 152dfe03796SJeremy L Thompson ? u : u+d*ncomp*nqpt*nelem, 153dfe03796SJeremy L Thompson tmode == CEED_TRANSPOSE 154dfe03796SJeremy L Thompson ? v : v+d*ncomp*nqpt*nelem); 155dfe03796SJeremy L Thompson CeedChk(ierr); 156dfe03796SJeremy L Thompson } 157a7bd39daSjeremylt } else { // Underintegration, P > Q 158a7bd39daSjeremylt CeedScalar *grad1d; 159a7bd39daSjeremylt ierr = CeedBasisGetGrad(basis, &grad1d); CeedChk(ierr); 160a7bd39daSjeremylt 161a7bd39daSjeremylt if (tmode == CEED_TRANSPOSE) { 162a7bd39daSjeremylt P = Q1d, Q = P1d; 163a7bd39daSjeremylt } 164a7bd39daSjeremylt CeedScalar tmp[2][nelem*ncomp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 165a7bd39daSjeremylt 166a7bd39daSjeremylt // Dim**2 contractions, apply grad when pass == dim 167a7bd39daSjeremylt for (CeedInt p=0; p<dim; p++) { 168a7bd39daSjeremylt CeedInt pre = ncomp*CeedIntPow(P, dim-1), post = nelem; 169a7bd39daSjeremylt for (CeedInt d=0; d<dim; d++) { 170a7bd39daSjeremylt ierr = CeedTensorContractApply(contract, pre, P, post, Q, 171a7bd39daSjeremylt (p==d)? grad1d : interp1d, 172a7bd39daSjeremylt tmode, add&&(d==dim-1), 173a7bd39daSjeremylt (d == 0 174a7bd39daSjeremylt ? (tmode == CEED_NOTRANSPOSE 175a7bd39daSjeremylt ? u : u+p*ncomp*nqpt*nelem) 176a7bd39daSjeremylt : tmp[d%2]), 177a7bd39daSjeremylt (d == dim-1 178a7bd39daSjeremylt ? (tmode == CEED_TRANSPOSE 179a7bd39daSjeremylt ? v : v+p*ncomp*nqpt*nelem) 180a7bd39daSjeremylt : tmp[(d+1)%2])); 181a7bd39daSjeremylt CeedChk(ierr); 182a7bd39daSjeremylt pre /= P; 183a7bd39daSjeremylt post *= Q; 184a7bd39daSjeremylt } 185a7bd39daSjeremylt } 186a7bd39daSjeremylt } 187a2b73c81Sjeremylt } break; 1888d94b059Sjeremylt // Retrieve interpolation weights 189a2b73c81Sjeremylt case CEED_EVAL_WEIGHT: { 19021617c04Sjeremylt if (tmode == CEED_TRANSPOSE) 1914ce2993fSjeremylt return CeedError(ceed, 1, 19221617c04Sjeremylt "CEED_EVAL_WEIGHT incompatible with CEED_TRANSPOSE"); 1934ce2993fSjeremylt CeedInt Q = Q1d; 1944ce2993fSjeremylt CeedScalar *qweight1d; 1954ce2993fSjeremylt ierr = CeedBasisGetQWeights(basis, &qweight1d); CeedChk(ierr); 19621617c04Sjeremylt for (CeedInt d=0; d<dim; d++) { 197b5cf12eeSjeremylt CeedInt pre = CeedIntPow(Q, dim-d-1), post = CeedIntPow(Q, d); 198a2b73c81Sjeremylt for (CeedInt i=0; i<pre; i++) 199a2b73c81Sjeremylt for (CeedInt j=0; j<Q; j++) 20084a01de5SJeremy L Thompson for (CeedInt k=0; k<post; k++) { 20184a01de5SJeremy L Thompson CeedScalar w = qweight1d[j] 20284a01de5SJeremy L Thompson * (d == 0 ? 1 : v[((i*Q + j)*post + k)*nelem]); 20384a01de5SJeremy L Thompson for (CeedInt e=0; e<nelem; e++) 20484a01de5SJeremy L Thompson v[((i*Q + j)*post + k)*nelem + e] = w; 20584a01de5SJeremy L Thompson } 20621617c04Sjeremylt } 207a2b73c81Sjeremylt } break; 2088d94b059Sjeremylt // Evaluate the divergence to/from the quadrature points 209a2b73c81Sjeremylt case CEED_EVAL_DIV: 2104ce2993fSjeremylt return CeedError(ceed, 1, "CEED_EVAL_DIV not supported"); 2118d94b059Sjeremylt // Evaluate the curl to/from the quadrature points 212a2b73c81Sjeremylt case CEED_EVAL_CURL: 2134ce2993fSjeremylt return CeedError(ceed, 1, "CEED_EVAL_CURL not supported"); 2148d94b059Sjeremylt // Take no action, BasisApply should not have been called 215a2b73c81Sjeremylt case CEED_EVAL_NONE: 2164ce2993fSjeremylt return CeedError(ceed, 1, 2174b8bea3bSJed Brown "CEED_EVAL_NONE does not make sense in this context"); 21821617c04Sjeremylt } 219a8de75f0Sjeremylt } else { 220a8de75f0Sjeremylt // Non-tensor basis 221a8de75f0Sjeremylt switch (emode) { 22284a01de5SJeremy L Thompson // Interpolate to/from quadrature points 223a8de75f0Sjeremylt case CEED_EVAL_INTERP: { 2248795c945Sjeremylt CeedInt P = nnodes, Q = nqpt; 2254ce2993fSjeremylt CeedScalar *interp; 2264ce2993fSjeremylt ierr = CeedBasisGetInterp(basis, &interp); CeedChk(ierr); 227a8de75f0Sjeremylt if (tmode == CEED_TRANSPOSE) { 2288795c945Sjeremylt P = nqpt; Q = nnodes; 229a8de75f0Sjeremylt } 2302f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, ncomp, P, nelem, Q, 23184a01de5SJeremy L Thompson interp, tmode, add, u, v); 232a8de75f0Sjeremylt CeedChk(ierr); 233a8de75f0Sjeremylt } 234a8de75f0Sjeremylt break; 23584a01de5SJeremy L Thompson // Evaluate the gradient to/from quadrature points 236a8de75f0Sjeremylt case CEED_EVAL_GRAD: { 2378795c945Sjeremylt CeedInt P = nnodes, Q = dim*nqpt; 2384ce2993fSjeremylt CeedScalar *grad; 2394ce2993fSjeremylt ierr = CeedBasisGetGrad(basis, &grad); CeedChk(ierr); 240a8de75f0Sjeremylt if (tmode == CEED_TRANSPOSE) { 2418795c945Sjeremylt P = dim*nqpt; Q = nnodes; 242a8de75f0Sjeremylt } 2432f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, ncomp, P, nelem, Q, 24484a01de5SJeremy L Thompson grad, tmode, add, u, v); 245a8de75f0Sjeremylt CeedChk(ierr); 246a8de75f0Sjeremylt } 247a8de75f0Sjeremylt break; 24884a01de5SJeremy L Thompson // Retrieve interpolation weights 249a8de75f0Sjeremylt case CEED_EVAL_WEIGHT: { 250a8de75f0Sjeremylt if (tmode == CEED_TRANSPOSE) 2514ce2993fSjeremylt return CeedError(ceed, 1, 252a8de75f0Sjeremylt "CEED_EVAL_WEIGHT incompatible with CEED_TRANSPOSE"); 2534ce2993fSjeremylt CeedScalar *qweight; 2544ce2993fSjeremylt ierr = CeedBasisGetQWeights(basis, &qweight); CeedChk(ierr); 255a8de75f0Sjeremylt for (CeedInt i=0; i<nqpt; i++) 25684a01de5SJeremy L Thompson for (CeedInt e=0; e<nelem; e++) 25784a01de5SJeremy L Thompson v[i*nelem + e] = qweight[i]; 258a8de75f0Sjeremylt } break; 25984a01de5SJeremy L Thompson // Evaluate the divergence to/from the quadrature points 260a8de75f0Sjeremylt case CEED_EVAL_DIV: 2614ce2993fSjeremylt return CeedError(ceed, 1, "CEED_EVAL_DIV not supported"); 26284a01de5SJeremy L Thompson // Evaluate the curl to/from the quadrature points 263a8de75f0Sjeremylt case CEED_EVAL_CURL: 2644ce2993fSjeremylt return CeedError(ceed, 1, "CEED_EVAL_CURL not supported"); 26584a01de5SJeremy L Thompson // Take no action, BasisApply should not have been called 266a8de75f0Sjeremylt case CEED_EVAL_NONE: 2674ce2993fSjeremylt return CeedError(ceed, 1, 268a8de75f0Sjeremylt "CEED_EVAL_NONE does not make sense in this context"); 269a8de75f0Sjeremylt } 270a8de75f0Sjeremylt } 271aedaa0e5Sjeremylt if (U) { 272aedaa0e5Sjeremylt ierr = CeedVectorRestoreArrayRead(U, &u); CeedChk(ierr); 273aedaa0e5Sjeremylt } 274aedaa0e5Sjeremylt ierr = CeedVectorRestoreArray(V, &v); CeedChk(ierr); 27521617c04Sjeremylt return 0; 27621617c04Sjeremylt } 27721617c04Sjeremylt 27884a01de5SJeremy L Thompson static int CeedBasisDestroyNonTensor_Ref(CeedBasis basis) { 2792f86a920SJeremy L Thompson int ierr; 2802f86a920SJeremy L Thompson CeedTensorContract contract; 2812f86a920SJeremy L Thompson ierr = CeedBasisGetTensorContract(basis, &contract); CeedChk(ierr); 2822f86a920SJeremy L Thompson ierr = CeedTensorContractDestroy(&contract); CeedChk(ierr); 28384a01de5SJeremy L Thompson return 0; 28484a01de5SJeremy L Thompson } 28584a01de5SJeremy L Thompson 28684a01de5SJeremy L Thompson static int CeedBasisDestroyTensor_Ref(CeedBasis basis) { 28784a01de5SJeremy L Thompson int ierr; 2882f86a920SJeremy L Thompson CeedTensorContract contract; 2892f86a920SJeremy L Thompson ierr = CeedBasisGetTensorContract(basis, &contract); CeedChk(ierr); 2902f86a920SJeremy L Thompson ierr = CeedTensorContractDestroy(&contract); CeedChk(ierr); 2912f86a920SJeremy L Thompson 29284a01de5SJeremy L Thompson CeedBasis_Ref *impl; 29384a01de5SJeremy L Thompson ierr = CeedBasisGetData(basis, (void *)&impl); CeedChk(ierr); 294dfe03796SJeremy L Thompson ierr = CeedFree(&impl->collograd1d); CeedChk(ierr); 29584a01de5SJeremy L Thompson ierr = CeedFree(&impl); CeedChk(ierr); 29684a01de5SJeremy L Thompson 29721617c04Sjeremylt return 0; 29821617c04Sjeremylt } 29921617c04Sjeremylt 300667bc5fcSjeremylt int CeedBasisCreateTensorH1_Ref(CeedInt dim, CeedInt P1d, 30121617c04Sjeremylt CeedInt Q1d, const CeedScalar *interp1d, 30221617c04Sjeremylt const CeedScalar *grad1d, 30321617c04Sjeremylt const CeedScalar *qref1d, 30421617c04Sjeremylt const CeedScalar *qweight1d, 30521617c04Sjeremylt CeedBasis basis) { 306fe2413ffSjeremylt int ierr; 307fe2413ffSjeremylt Ceed ceed; 308fe2413ffSjeremylt ierr = CeedBasisGetCeed(basis, &ceed); CeedChk(ierr); 30984a01de5SJeremy L Thompson CeedBasis_Ref *impl; 31084a01de5SJeremy L Thompson ierr = CeedCalloc(1, &impl); CeedChk(ierr); 311dfe03796SJeremy L Thompson // Check for collocated interp 312dfe03796SJeremy L Thompson if (Q1d == P1d) { 313dfe03796SJeremy L Thompson bool collocated = 1; 314dfe03796SJeremy L Thompson for (CeedInt i=0; i<P1d; i++) { 315dfe03796SJeremy L Thompson collocated = collocated && (fabs(interp1d[i+P1d*i] - 1.0) < 1e-14); 316dfe03796SJeremy L Thompson for (CeedInt j=0; j<P1d; j++) 317dfe03796SJeremy L Thompson if (j != i) 318dfe03796SJeremy L Thompson collocated = collocated && (fabs(interp1d[j+P1d*i]) < 1e-14); 319dfe03796SJeremy L Thompson } 320dfe03796SJeremy L Thompson impl->collointerp = collocated; 321dfe03796SJeremy L Thompson } 322dfe03796SJeremy L Thompson // Calculate collocated grad 323dfe03796SJeremy L Thompson if (Q1d >= P1d && !impl->collointerp) { 324dfe03796SJeremy L Thompson ierr = CeedMalloc(Q1d*Q1d, &impl->collograd1d); CeedChk(ierr); 325dfe03796SJeremy L Thompson ierr = CeedBasisGetCollocatedGrad(basis, impl->collograd1d); CeedChk(ierr); 326a7bd39daSjeremylt } 32784a01de5SJeremy L Thompson ierr = CeedBasisSetData(basis, (void *)&impl); CeedChk(ierr); 328fe2413ffSjeremylt 3292f86a920SJeremy L Thompson Ceed parent; 330de686571SJeremy L Thompson ierr = CeedGetParent(ceed, &parent); CeedChk(ierr); 3312f86a920SJeremy L Thompson CeedTensorContract contract; 332c71e1dcdSjeremylt ierr = CeedTensorContractCreate(parent, basis, &contract); CeedChk(ierr); 3332f86a920SJeremy L Thompson ierr = CeedBasisSetTensorContract(basis, &contract); CeedChk(ierr); 3342f86a920SJeremy L Thompson 335fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Apply", 336fe2413ffSjeremylt CeedBasisApply_Ref); CeedChk(ierr); 337fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Destroy", 33884a01de5SJeremy L Thompson CeedBasisDestroyTensor_Ref); CeedChk(ierr); 33921617c04Sjeremylt return 0; 34021617c04Sjeremylt } 341a8de75f0Sjeremylt 34284a01de5SJeremy L Thompson 34384a01de5SJeremy L Thompson 344667bc5fcSjeremylt int CeedBasisCreateH1_Ref(CeedElemTopology topo, CeedInt dim, 3458795c945Sjeremylt CeedInt nnodes, CeedInt nqpts, 346a8de75f0Sjeremylt const CeedScalar *interp, 347a8de75f0Sjeremylt const CeedScalar *grad, 348a8de75f0Sjeremylt const CeedScalar *qref, 349a8de75f0Sjeremylt const CeedScalar *qweight, 350a8de75f0Sjeremylt CeedBasis basis) { 351fe2413ffSjeremylt int ierr; 352fe2413ffSjeremylt Ceed ceed; 353fe2413ffSjeremylt ierr = CeedBasisGetCeed(basis, &ceed); CeedChk(ierr); 354fe2413ffSjeremylt 355c71e1dcdSjeremylt Ceed parent; 356c71e1dcdSjeremylt ierr = CeedGetParent(ceed, &parent); CeedChk(ierr); 3572f86a920SJeremy L Thompson CeedTensorContract contract; 358c71e1dcdSjeremylt ierr = CeedTensorContractCreate(parent, basis, &contract); CeedChk(ierr); 3592f86a920SJeremy L Thompson ierr = CeedBasisSetTensorContract(basis, &contract); CeedChk(ierr); 3602f86a920SJeremy L Thompson 361fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Apply", 362fe2413ffSjeremylt CeedBasisApply_Ref); CeedChk(ierr); 363fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Destroy", 36484a01de5SJeremy L Thompson CeedBasisDestroyNonTensor_Ref); CeedChk(ierr); 36584a01de5SJeremy L Thompson 366a8de75f0Sjeremylt return 0; 367a8de75f0Sjeremylt } 368