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 19f10650afSjeremylt //------------------------------------------------------------------------------ 20f10650afSjeremylt // Basis Apply 21f10650afSjeremylt //------------------------------------------------------------------------------ 22d3181881Sjeremylt static int CeedBasisApply_Ref(CeedBasis basis, CeedInt nelem, 23d3181881Sjeremylt CeedTransposeMode tmode, CeedEvalMode emode, 24aedaa0e5Sjeremylt CeedVector U, CeedVector V) { 2521617c04Sjeremylt int ierr; 264ce2993fSjeremylt Ceed ceed; 274ce2993fSjeremylt ierr = CeedBasisGetCeed(basis, &ceed); CeedChk(ierr); 288795c945Sjeremylt CeedInt dim, ncomp, nnodes, nqpt; 294ce2993fSjeremylt ierr = CeedBasisGetDimension(basis, &dim); CeedChk(ierr); 304ce2993fSjeremylt ierr = CeedBasisGetNumComponents(basis, &ncomp); CeedChk(ierr); 318795c945Sjeremylt ierr = CeedBasisGetNumNodes(basis, &nnodes); CeedChk(ierr); 324ce2993fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis, &nqpt); CeedChk(ierr); 332f86a920SJeremy L Thompson CeedTensorContract contract; 342f86a920SJeremy L Thompson ierr = CeedBasisGetTensorContract(basis, &contract); CeedChk(ierr); 3521617c04Sjeremylt const CeedInt add = (tmode == CEED_TRANSPOSE); 36aedaa0e5Sjeremylt const CeedScalar *u; 37aedaa0e5Sjeremylt CeedScalar *v; 38a7b7f929Sjeremylt if (U != CEED_VECTOR_NONE) { 39aedaa0e5Sjeremylt ierr = CeedVectorGetArrayRead(U, CEED_MEM_HOST, &u); CeedChk(ierr); 40aedaa0e5Sjeremylt } else if (emode != CEED_EVAL_WEIGHT) { 41c042f62fSJeremy L Thompson // LCOV_EXCL_START 42aedaa0e5Sjeremylt return CeedError(ceed, 1, 43aedaa0e5Sjeremylt "An input vector is required for this CeedEvalMode"); 44c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 45aedaa0e5Sjeremylt } 46aedaa0e5Sjeremylt ierr = CeedVectorGetArray(V, CEED_MEM_HOST, &v); CeedChk(ierr); 4721617c04Sjeremylt 488d94b059Sjeremylt // Clear v if operating in transpose 4921617c04Sjeremylt if (tmode == CEED_TRANSPOSE) { 508795c945Sjeremylt const CeedInt vsize = nelem*ncomp*nnodes; 5121617c04Sjeremylt for (CeedInt i = 0; i < vsize; i++) 5284a01de5SJeremy L Thompson v[i] = (CeedScalar) 0.0; 5321617c04Sjeremylt } 544ce2993fSjeremylt bool tensorbasis; 554ce2993fSjeremylt ierr = CeedBasisGetTensorStatus(basis, &tensorbasis); CeedChk(ierr); 5684a01de5SJeremy L Thompson // Tensor basis 574ce2993fSjeremylt if (tensorbasis) { 584ce2993fSjeremylt CeedInt P1d, Q1d; 594ce2993fSjeremylt ierr = CeedBasisGetNumNodes1D(basis, &P1d); CeedChk(ierr); 604ce2993fSjeremylt ierr = CeedBasisGetNumQuadraturePoints1D(basis, &Q1d); CeedChk(ierr); 61a2b73c81Sjeremylt switch (emode) { 628d94b059Sjeremylt // Interpolate to/from quadrature points 63a2b73c81Sjeremylt case CEED_EVAL_INTERP: { 64dfe03796SJeremy L Thompson CeedBasis_Ref *impl; 65dfe03796SJeremy L Thompson ierr = CeedBasisGetData(basis, (void *)&impl); CeedChk(ierr); 66dfe03796SJeremy L Thompson if (impl->collointerp) { 67dfe03796SJeremy L Thompson memcpy(v, u, nelem*ncomp*nnodes*sizeof(u[0])); 68dfe03796SJeremy L Thompson } else { 694ce2993fSjeremylt CeedInt P = P1d, Q = Q1d; 7021617c04Sjeremylt if (tmode == CEED_TRANSPOSE) { 714ce2993fSjeremylt P = Q1d; Q = P1d; 7221617c04Sjeremylt } 7384a01de5SJeremy L Thompson CeedInt pre = ncomp*CeedIntPow(P, dim-1), post = nelem; 7484a01de5SJeremy L Thompson CeedScalar tmp[2][nelem*ncomp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 75*6c58de82SJeremy L Thompson const CeedScalar *interp1d; 7600f91b2bSjeremylt ierr = CeedBasisGetInterp1D(basis, &interp1d); CeedChk(ierr); 7721617c04Sjeremylt for (CeedInt d=0; d<dim; d++) { 782f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 7984a01de5SJeremy L Thompson interp1d, tmode, add&&(d==dim-1), 80dfe03796SJeremy L Thompson d==0?u:tmp[d%2], 81dfe03796SJeremy L Thompson d==dim-1?v:tmp[(d+1)%2]); 8221617c04Sjeremylt CeedChk(ierr); 8321617c04Sjeremylt pre /= P; 8421617c04Sjeremylt post *= Q; 8521617c04Sjeremylt } 86dfe03796SJeremy L Thompson } 87a2b73c81Sjeremylt } break; 888d94b059Sjeremylt // Evaluate the gradient to/from quadrature points 89a2b73c81Sjeremylt case CEED_EVAL_GRAD: { 9021617c04Sjeremylt // In CEED_NOTRANSPOSE mode: 91ecf6354eSJed Brown // u has shape [dim, ncomp, P^dim, nelem], row-major layout 92ecf6354eSJed Brown // v has shape [dim, ncomp, Q^dim, nelem], row-major layout 9321617c04Sjeremylt // In CEED_TRANSPOSE mode, the sizes of u and v are switched. 9484a01de5SJeremy L Thompson CeedInt P = P1d, Q = Q1d; 9521617c04Sjeremylt if (tmode == CEED_TRANSPOSE) { 9684a01de5SJeremy L Thompson P = Q1d, Q = Q1d; 9721617c04Sjeremylt } 9884a01de5SJeremy L Thompson CeedBasis_Ref *impl; 9984a01de5SJeremy L Thompson ierr = CeedBasisGetData(basis, (void *)&impl); CeedChk(ierr); 10084a01de5SJeremy L Thompson CeedInt pre = ncomp*CeedIntPow(P, dim-1), post = nelem; 101*6c58de82SJeremy L Thompson const CeedScalar *interp1d; 10200f91b2bSjeremylt ierr = CeedBasisGetInterp1D(basis, &interp1d); CeedChk(ierr); 103dfe03796SJeremy L Thompson if (impl->collograd1d) { 104a7bd39daSjeremylt CeedScalar tmp[2][nelem*ncomp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 105a7bd39daSjeremylt CeedScalar interp[nelem*ncomp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 10684a01de5SJeremy L Thompson // Interpolate to quadrature points (NoTranspose) 10784a01de5SJeremy L Thompson // or Grad to quadrature points (Transpose) 10821617c04Sjeremylt for (CeedInt d=0; d<dim; d++) { 1092f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 11084a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 11184a01de5SJeremy L Thompson ? interp1d 112dfe03796SJeremy L Thompson : impl->collograd1d), 11384a01de5SJeremy L Thompson tmode, add&&(d>0), 11484a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 11584a01de5SJeremy L Thompson ? (d==0?u:tmp[d%2]) 11684a01de5SJeremy L Thompson : u + d*nqpt*ncomp*nelem), 11784a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 11884a01de5SJeremy L Thompson ? (d==dim-1?interp:tmp[(d+1)%2]) 11984a01de5SJeremy L Thompson : interp)); 12021617c04Sjeremylt CeedChk(ierr); 12121617c04Sjeremylt pre /= P; 12221617c04Sjeremylt post *= Q; 12321617c04Sjeremylt } 12484a01de5SJeremy L Thompson // Grad to quadrature points (NoTranspose) 1258795c945Sjeremylt // or Interpolate to nodes (Transpose) 12684a01de5SJeremy L Thompson P = Q1d, Q = Q1d; 12784a01de5SJeremy L Thompson if (tmode == CEED_TRANSPOSE) { 12884a01de5SJeremy L Thompson P = Q1d, Q = P1d; 12984a01de5SJeremy L Thompson } 13084a01de5SJeremy L Thompson pre = ncomp*CeedIntPow(P, dim-1), post = nelem; 13184a01de5SJeremy L Thompson for (CeedInt d=0; d<dim; d++) { 1322f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 13384a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 134dfe03796SJeremy L Thompson ? impl->collograd1d 13584a01de5SJeremy L Thompson : interp1d), 13684a01de5SJeremy L Thompson tmode, add&&(d==dim-1), 13784a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 13884a01de5SJeremy L Thompson ? interp 13984a01de5SJeremy L Thompson : (d==0?interp:tmp[d%2])), 14084a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 14184a01de5SJeremy L Thompson ? v + d*nqpt*ncomp*nelem 14284a01de5SJeremy L Thompson : (d==dim-1?v:tmp[(d+1)%2]))); 14384a01de5SJeremy L Thompson CeedChk(ierr); 14484a01de5SJeremy L Thompson pre /= P; 14584a01de5SJeremy L Thompson post *= Q; 14621617c04Sjeremylt } 147dfe03796SJeremy L Thompson } else if (impl->collointerp) { // Qpts collocated with nodes 148*6c58de82SJeremy L Thompson const CeedScalar *grad1d; 14900f91b2bSjeremylt ierr = CeedBasisGetGrad1D(basis, &grad1d); CeedChk(ierr); 150dfe03796SJeremy L Thompson 151dfe03796SJeremy L Thompson // Dim contractions, identity in other directions 152dfe03796SJeremy L Thompson CeedInt pre = ncomp*CeedIntPow(P, dim-1), post = nelem; 153c6158135Sjeremylt for (CeedInt d=0; d<dim; d++) { 154dfe03796SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 155a1dbd226Sjeremylt grad1d, tmode, add&&(d>0), 156dfe03796SJeremy L Thompson tmode == CEED_NOTRANSPOSE 157dfe03796SJeremy L Thompson ? u : u+d*ncomp*nqpt*nelem, 158dfe03796SJeremy L Thompson tmode == CEED_TRANSPOSE 159dfe03796SJeremy L Thompson ? v : v+d*ncomp*nqpt*nelem); 160dfe03796SJeremy L Thompson CeedChk(ierr); 161c6158135Sjeremylt pre /= P; 162c6158135Sjeremylt post *= Q; 163dfe03796SJeremy L Thompson } 164a7bd39daSjeremylt } else { // Underintegration, P > Q 165*6c58de82SJeremy L Thompson const CeedScalar *grad1d; 16600f91b2bSjeremylt ierr = CeedBasisGetGrad1D(basis, &grad1d); CeedChk(ierr); 167a7bd39daSjeremylt 168a7bd39daSjeremylt if (tmode == CEED_TRANSPOSE) { 169a7bd39daSjeremylt P = Q1d, Q = P1d; 170a7bd39daSjeremylt } 171a7bd39daSjeremylt CeedScalar tmp[2][nelem*ncomp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 172a7bd39daSjeremylt 173a7bd39daSjeremylt // Dim**2 contractions, apply grad when pass == dim 174a7bd39daSjeremylt for (CeedInt p=0; p<dim; p++) { 175a7bd39daSjeremylt CeedInt pre = ncomp*CeedIntPow(P, dim-1), post = nelem; 176a7bd39daSjeremylt for (CeedInt d=0; d<dim; d++) { 177a7bd39daSjeremylt ierr = CeedTensorContractApply(contract, pre, P, post, Q, 178a7bd39daSjeremylt (p==d)? grad1d : interp1d, 179a7bd39daSjeremylt tmode, add&&(d==dim-1), 180a7bd39daSjeremylt (d == 0 181a7bd39daSjeremylt ? (tmode == CEED_NOTRANSPOSE 182a7bd39daSjeremylt ? u : u+p*ncomp*nqpt*nelem) 183a7bd39daSjeremylt : tmp[d%2]), 184a7bd39daSjeremylt (d == dim-1 185a7bd39daSjeremylt ? (tmode == CEED_TRANSPOSE 186a7bd39daSjeremylt ? v : v+p*ncomp*nqpt*nelem) 187a7bd39daSjeremylt : tmp[(d+1)%2])); 188a7bd39daSjeremylt CeedChk(ierr); 189a7bd39daSjeremylt pre /= P; 190a7bd39daSjeremylt post *= Q; 191a7bd39daSjeremylt } 192a7bd39daSjeremylt } 193a7bd39daSjeremylt } 194a2b73c81Sjeremylt } break; 1958d94b059Sjeremylt // Retrieve interpolation weights 196a2b73c81Sjeremylt case CEED_EVAL_WEIGHT: { 19721617c04Sjeremylt if (tmode == CEED_TRANSPOSE) 198c042f62fSJeremy L Thompson // LCOV_EXCL_START 1994ce2993fSjeremylt return CeedError(ceed, 1, 20021617c04Sjeremylt "CEED_EVAL_WEIGHT incompatible with CEED_TRANSPOSE"); 201c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 2024ce2993fSjeremylt CeedInt Q = Q1d; 203*6c58de82SJeremy L Thompson const CeedScalar *qweight1d; 2044ce2993fSjeremylt ierr = CeedBasisGetQWeights(basis, &qweight1d); CeedChk(ierr); 20521617c04Sjeremylt for (CeedInt d=0; d<dim; d++) { 206b5cf12eeSjeremylt CeedInt pre = CeedIntPow(Q, dim-d-1), post = CeedIntPow(Q, d); 207a2b73c81Sjeremylt for (CeedInt i=0; i<pre; i++) 208a2b73c81Sjeremylt for (CeedInt j=0; j<Q; j++) 20984a01de5SJeremy L Thompson for (CeedInt k=0; k<post; k++) { 21084a01de5SJeremy L Thompson CeedScalar w = qweight1d[j] 21184a01de5SJeremy L Thompson * (d == 0 ? 1 : v[((i*Q + j)*post + k)*nelem]); 21284a01de5SJeremy L Thompson for (CeedInt e=0; e<nelem; e++) 21384a01de5SJeremy L Thompson v[((i*Q + j)*post + k)*nelem + e] = w; 21484a01de5SJeremy L Thompson } 21521617c04Sjeremylt } 216a2b73c81Sjeremylt } break; 217c042f62fSJeremy L Thompson // LCOV_EXCL_START 2188d94b059Sjeremylt // Evaluate the divergence to/from the quadrature points 219a2b73c81Sjeremylt case CEED_EVAL_DIV: 2204ce2993fSjeremylt return CeedError(ceed, 1, "CEED_EVAL_DIV not supported"); 2218d94b059Sjeremylt // Evaluate the curl to/from the quadrature points 222a2b73c81Sjeremylt case CEED_EVAL_CURL: 2234ce2993fSjeremylt return CeedError(ceed, 1, "CEED_EVAL_CURL not supported"); 2248d94b059Sjeremylt // Take no action, BasisApply should not have been called 225a2b73c81Sjeremylt case CEED_EVAL_NONE: 2264ce2993fSjeremylt return CeedError(ceed, 1, 2274b8bea3bSJed Brown "CEED_EVAL_NONE does not make sense in this context"); 228c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 22921617c04Sjeremylt } 230a8de75f0Sjeremylt } else { 231a8de75f0Sjeremylt // Non-tensor basis 232a8de75f0Sjeremylt switch (emode) { 23384a01de5SJeremy L Thompson // Interpolate to/from quadrature points 234a8de75f0Sjeremylt case CEED_EVAL_INTERP: { 2358795c945Sjeremylt CeedInt P = nnodes, Q = nqpt; 236*6c58de82SJeremy L Thompson const CeedScalar *interp; 2374ce2993fSjeremylt ierr = CeedBasisGetInterp(basis, &interp); CeedChk(ierr); 238a8de75f0Sjeremylt if (tmode == CEED_TRANSPOSE) { 2398795c945Sjeremylt P = nqpt; Q = nnodes; 240a8de75f0Sjeremylt } 2412f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, ncomp, P, nelem, Q, 24284a01de5SJeremy L Thompson interp, tmode, add, u, v); 243a8de75f0Sjeremylt CeedChk(ierr); 244a8de75f0Sjeremylt } 245a8de75f0Sjeremylt break; 24684a01de5SJeremy L Thompson // Evaluate the gradient to/from quadrature points 247a8de75f0Sjeremylt case CEED_EVAL_GRAD: { 248475a782bSnbeams CeedInt P = nnodes, Q = nqpt; 249475a782bSnbeams CeedInt dimstride = nqpt * ncomp * nelem; 250475a782bSnbeams CeedInt gradstride = nqpt * nnodes; 251*6c58de82SJeremy L Thompson const CeedScalar *grad; 2524ce2993fSjeremylt ierr = CeedBasisGetGrad(basis, &grad); CeedChk(ierr); 253a8de75f0Sjeremylt if (tmode == CEED_TRANSPOSE) { 254475a782bSnbeams P = nqpt; Q = nnodes; 255475a782bSnbeams for (CeedInt d = 0; d < dim; d++) { 2562f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, ncomp, P, nelem, Q, 257475a782bSnbeams grad + d * gradstride, tmode, add, 258475a782bSnbeams u + d * dimstride, v); CeedChk(ierr); 259475a782bSnbeams } 260475a782bSnbeams } else { 261475a782bSnbeams for (CeedInt d = 0; d < dim; d++) { 262475a782bSnbeams ierr = CeedTensorContractApply(contract, ncomp, P, nelem, Q, 263475a782bSnbeams grad + d * gradstride, tmode, add, 264475a782bSnbeams u, v + d * dimstride); CeedChk(ierr); 265475a782bSnbeams } 266475a782bSnbeams } 267a8de75f0Sjeremylt } 268a8de75f0Sjeremylt break; 26984a01de5SJeremy L Thompson // Retrieve interpolation weights 270a8de75f0Sjeremylt case CEED_EVAL_WEIGHT: { 271a8de75f0Sjeremylt if (tmode == CEED_TRANSPOSE) 272c042f62fSJeremy L Thompson // LCOV_EXCL_START 2734ce2993fSjeremylt return CeedError(ceed, 1, 274a8de75f0Sjeremylt "CEED_EVAL_WEIGHT incompatible with CEED_TRANSPOSE"); 275c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 276*6c58de82SJeremy L Thompson const CeedScalar *qweight; 2774ce2993fSjeremylt ierr = CeedBasisGetQWeights(basis, &qweight); CeedChk(ierr); 278a8de75f0Sjeremylt for (CeedInt i=0; i<nqpt; i++) 27984a01de5SJeremy L Thompson for (CeedInt e=0; e<nelem; e++) 28084a01de5SJeremy L Thompson v[i*nelem + e] = qweight[i]; 281a8de75f0Sjeremylt } break; 282c042f62fSJeremy L Thompson // LCOV_EXCL_START 28384a01de5SJeremy L Thompson // Evaluate the divergence to/from the quadrature points 284a8de75f0Sjeremylt case CEED_EVAL_DIV: 2854ce2993fSjeremylt return CeedError(ceed, 1, "CEED_EVAL_DIV not supported"); 28684a01de5SJeremy L Thompson // Evaluate the curl to/from the quadrature points 287a8de75f0Sjeremylt case CEED_EVAL_CURL: 2884ce2993fSjeremylt return CeedError(ceed, 1, "CEED_EVAL_CURL not supported"); 28984a01de5SJeremy L Thompson // Take no action, BasisApply should not have been called 290a8de75f0Sjeremylt case CEED_EVAL_NONE: 2914ce2993fSjeremylt return CeedError(ceed, 1, 292a8de75f0Sjeremylt "CEED_EVAL_NONE does not make sense in this context"); 293c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 294a8de75f0Sjeremylt } 295a8de75f0Sjeremylt } 296a7b7f929Sjeremylt if (U != CEED_VECTOR_NONE) { 297aedaa0e5Sjeremylt ierr = CeedVectorRestoreArrayRead(U, &u); CeedChk(ierr); 298aedaa0e5Sjeremylt } 299aedaa0e5Sjeremylt ierr = CeedVectorRestoreArray(V, &v); CeedChk(ierr); 30021617c04Sjeremylt return 0; 30121617c04Sjeremylt } 30221617c04Sjeremylt 303f10650afSjeremylt //------------------------------------------------------------------------------ 304f10650afSjeremylt // Basis Destroy Non-Tensor 305f10650afSjeremylt //------------------------------------------------------------------------------ 30684a01de5SJeremy L Thompson static int CeedBasisDestroyNonTensor_Ref(CeedBasis basis) { 3072f86a920SJeremy L Thompson int ierr; 3082f86a920SJeremy L Thompson CeedTensorContract contract; 3092f86a920SJeremy L Thompson ierr = CeedBasisGetTensorContract(basis, &contract); CeedChk(ierr); 3102f86a920SJeremy L Thompson ierr = CeedTensorContractDestroy(&contract); CeedChk(ierr); 31184a01de5SJeremy L Thompson return 0; 31284a01de5SJeremy L Thompson } 31384a01de5SJeremy L Thompson 314f10650afSjeremylt //------------------------------------------------------------------------------ 315f10650afSjeremylt // Basis Create Non-Tensor 316f10650afSjeremylt //------------------------------------------------------------------------------ 317f10650afSjeremylt int CeedBasisCreateH1_Ref(CeedElemTopology topo, CeedInt dim, 318f10650afSjeremylt CeedInt nnodes, CeedInt nqpts, 319f10650afSjeremylt const CeedScalar *interp, 320f10650afSjeremylt const CeedScalar *grad, 321f10650afSjeremylt const CeedScalar *qref, 322f10650afSjeremylt const CeedScalar *qweight, 323f10650afSjeremylt CeedBasis basis) { 324f10650afSjeremylt int ierr; 325f10650afSjeremylt Ceed ceed; 326f10650afSjeremylt ierr = CeedBasisGetCeed(basis, &ceed); CeedChk(ierr); 327f10650afSjeremylt 328f10650afSjeremylt Ceed parent; 329f10650afSjeremylt ierr = CeedGetParent(ceed, &parent); CeedChk(ierr); 330f10650afSjeremylt CeedTensorContract contract; 331f10650afSjeremylt ierr = CeedTensorContractCreate(parent, basis, &contract); CeedChk(ierr); 332f10650afSjeremylt ierr = CeedBasisSetTensorContract(basis, &contract); CeedChk(ierr); 333f10650afSjeremylt 334f10650afSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Apply", 335f10650afSjeremylt CeedBasisApply_Ref); CeedChk(ierr); 336f10650afSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Destroy", 337f10650afSjeremylt CeedBasisDestroyNonTensor_Ref); CeedChk(ierr); 338f10650afSjeremylt 339f10650afSjeremylt return 0; 340f10650afSjeremylt } 341f10650afSjeremylt 342f10650afSjeremylt //------------------------------------------------------------------------------ 343f10650afSjeremylt // Basis Destroy Tensor 344f10650afSjeremylt //------------------------------------------------------------------------------ 34584a01de5SJeremy L Thompson static int CeedBasisDestroyTensor_Ref(CeedBasis basis) { 34684a01de5SJeremy L Thompson int ierr; 3472f86a920SJeremy L Thompson CeedTensorContract contract; 3482f86a920SJeremy L Thompson ierr = CeedBasisGetTensorContract(basis, &contract); CeedChk(ierr); 3492f86a920SJeremy L Thompson ierr = CeedTensorContractDestroy(&contract); CeedChk(ierr); 3502f86a920SJeremy L Thompson 35184a01de5SJeremy L Thompson CeedBasis_Ref *impl; 35284a01de5SJeremy L Thompson ierr = CeedBasisGetData(basis, (void *)&impl); CeedChk(ierr); 353dfe03796SJeremy L Thompson ierr = CeedFree(&impl->collograd1d); CeedChk(ierr); 35484a01de5SJeremy L Thompson ierr = CeedFree(&impl); CeedChk(ierr); 35584a01de5SJeremy L Thompson 35621617c04Sjeremylt return 0; 35721617c04Sjeremylt } 35821617c04Sjeremylt 359f10650afSjeremylt //------------------------------------------------------------------------------ 360f10650afSjeremylt // Basis Create Tensor 361f10650afSjeremylt //------------------------------------------------------------------------------ 362667bc5fcSjeremylt int CeedBasisCreateTensorH1_Ref(CeedInt dim, CeedInt P1d, 36321617c04Sjeremylt CeedInt Q1d, const CeedScalar *interp1d, 36421617c04Sjeremylt const CeedScalar *grad1d, 36521617c04Sjeremylt const CeedScalar *qref1d, 36621617c04Sjeremylt const CeedScalar *qweight1d, 36721617c04Sjeremylt CeedBasis basis) { 368fe2413ffSjeremylt int ierr; 369fe2413ffSjeremylt Ceed ceed; 370fe2413ffSjeremylt ierr = CeedBasisGetCeed(basis, &ceed); CeedChk(ierr); 37184a01de5SJeremy L Thompson CeedBasis_Ref *impl; 37284a01de5SJeremy L Thompson ierr = CeedCalloc(1, &impl); CeedChk(ierr); 373dfe03796SJeremy L Thompson // Check for collocated interp 374dfe03796SJeremy L Thompson if (Q1d == P1d) { 375dfe03796SJeremy L Thompson bool collocated = 1; 376dfe03796SJeremy L Thompson for (CeedInt i=0; i<P1d; i++) { 377dfe03796SJeremy L Thompson collocated = collocated && (fabs(interp1d[i+P1d*i] - 1.0) < 1e-14); 378dfe03796SJeremy L Thompson for (CeedInt j=0; j<P1d; j++) 379dfe03796SJeremy L Thompson if (j != i) 380dfe03796SJeremy L Thompson collocated = collocated && (fabs(interp1d[j+P1d*i]) < 1e-14); 381dfe03796SJeremy L Thompson } 382dfe03796SJeremy L Thompson impl->collointerp = collocated; 383dfe03796SJeremy L Thompson } 384dfe03796SJeremy L Thompson // Calculate collocated grad 385dfe03796SJeremy L Thompson if (Q1d >= P1d && !impl->collointerp) { 386dfe03796SJeremy L Thompson ierr = CeedMalloc(Q1d*Q1d, &impl->collograd1d); CeedChk(ierr); 387dfe03796SJeremy L Thompson ierr = CeedBasisGetCollocatedGrad(basis, impl->collograd1d); CeedChk(ierr); 388a7bd39daSjeremylt } 38984a01de5SJeremy L Thompson ierr = CeedBasisSetData(basis, (void *)&impl); CeedChk(ierr); 390fe2413ffSjeremylt 3912f86a920SJeremy L Thompson Ceed parent; 392de686571SJeremy L Thompson ierr = CeedGetParent(ceed, &parent); CeedChk(ierr); 3932f86a920SJeremy L Thompson CeedTensorContract contract; 394c71e1dcdSjeremylt ierr = CeedTensorContractCreate(parent, basis, &contract); CeedChk(ierr); 3952f86a920SJeremy L Thompson ierr = CeedBasisSetTensorContract(basis, &contract); CeedChk(ierr); 3962f86a920SJeremy L Thompson 397fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Apply", 398fe2413ffSjeremylt CeedBasisApply_Ref); CeedChk(ierr); 399fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Destroy", 40084a01de5SJeremy L Thompson CeedBasisDestroyTensor_Ref); CeedChk(ierr); 40121617c04Sjeremylt return 0; 40221617c04Sjeremylt } 403a8de75f0Sjeremylt 404f10650afSjeremylt //------------------------------------------------------------------------------ 405