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 173d576824SJeremy L Thompson #include <ceed.h> 183d576824SJeremy L Thompson #include <ceed-backend.h> 193d576824SJeremy L Thompson #include <math.h> 203d576824SJeremy L Thompson #include <stdbool.h> 213d576824SJeremy L Thompson #include <string.h> 2221617c04Sjeremylt #include "ceed-ref.h" 2321617c04Sjeremylt 24f10650afSjeremylt //------------------------------------------------------------------------------ 25f10650afSjeremylt // Basis Apply 26f10650afSjeremylt //------------------------------------------------------------------------------ 27d3181881Sjeremylt static int CeedBasisApply_Ref(CeedBasis basis, CeedInt nelem, 28d3181881Sjeremylt CeedTransposeMode tmode, CeedEvalMode emode, 29aedaa0e5Sjeremylt CeedVector U, CeedVector V) { 3021617c04Sjeremylt int ierr; 314ce2993fSjeremylt Ceed ceed; 32*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetCeed(basis, &ceed); CeedChkBackend(ierr); 338795c945Sjeremylt CeedInt dim, ncomp, nnodes, nqpt; 34*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(basis, &dim); CeedChkBackend(ierr); 35*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetNumComponents(basis, &ncomp); CeedChkBackend(ierr); 36*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetNumNodes(basis, &nnodes); CeedChkBackend(ierr); 37*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basis, &nqpt); CeedChkBackend(ierr); 382f86a920SJeremy L Thompson CeedTensorContract contract; 39*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetTensorContract(basis, &contract); CeedChkBackend(ierr); 4021617c04Sjeremylt const CeedInt add = (tmode == CEED_TRANSPOSE); 41aedaa0e5Sjeremylt const CeedScalar *u; 42aedaa0e5Sjeremylt CeedScalar *v; 43a7b7f929Sjeremylt if (U != CEED_VECTOR_NONE) { 44*e15f9bd0SJeremy L Thompson ierr = CeedVectorGetArrayRead(U, CEED_MEM_HOST, &u); CeedChkBackend(ierr); 45aedaa0e5Sjeremylt } else if (emode != CEED_EVAL_WEIGHT) { 46c042f62fSJeremy L Thompson // LCOV_EXCL_START 47*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 48aedaa0e5Sjeremylt "An input vector is required for this CeedEvalMode"); 49c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 50aedaa0e5Sjeremylt } 51*e15f9bd0SJeremy L Thompson ierr = CeedVectorGetArray(V, CEED_MEM_HOST, &v); CeedChkBackend(ierr); 5221617c04Sjeremylt 538d94b059Sjeremylt // Clear v if operating in transpose 5421617c04Sjeremylt if (tmode == CEED_TRANSPOSE) { 558795c945Sjeremylt const CeedInt vsize = nelem*ncomp*nnodes; 5621617c04Sjeremylt for (CeedInt i = 0; i < vsize; i++) 5784a01de5SJeremy L Thompson v[i] = (CeedScalar) 0.0; 5821617c04Sjeremylt } 594ce2993fSjeremylt bool tensorbasis; 60*e15f9bd0SJeremy L Thompson ierr = CeedBasisIsTensor(basis, &tensorbasis); CeedChkBackend(ierr); 6184a01de5SJeremy L Thompson // Tensor basis 624ce2993fSjeremylt if (tensorbasis) { 634ce2993fSjeremylt CeedInt P1d, Q1d; 64*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetNumNodes1D(basis, &P1d); CeedChkBackend(ierr); 65*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints1D(basis, &Q1d); CeedChkBackend(ierr); 66a2b73c81Sjeremylt switch (emode) { 678d94b059Sjeremylt // Interpolate to/from quadrature points 68a2b73c81Sjeremylt case CEED_EVAL_INTERP: { 69dfe03796SJeremy L Thompson CeedBasis_Ref *impl; 70*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetData(basis, &impl); CeedChkBackend(ierr); 71dfe03796SJeremy L Thompson if (impl->collointerp) { 72dfe03796SJeremy L Thompson memcpy(v, u, nelem*ncomp*nnodes*sizeof(u[0])); 73dfe03796SJeremy L Thompson } else { 744ce2993fSjeremylt CeedInt P = P1d, Q = Q1d; 7521617c04Sjeremylt if (tmode == CEED_TRANSPOSE) { 764ce2993fSjeremylt P = Q1d; Q = P1d; 7721617c04Sjeremylt } 7884a01de5SJeremy L Thompson CeedInt pre = ncomp*CeedIntPow(P, dim-1), post = nelem; 7984a01de5SJeremy L Thompson CeedScalar tmp[2][nelem*ncomp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 806c58de82SJeremy L Thompson const CeedScalar *interp1d; 81*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetInterp1D(basis, &interp1d); CeedChkBackend(ierr); 8221617c04Sjeremylt for (CeedInt d=0; d<dim; d++) { 832f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 8484a01de5SJeremy L Thompson interp1d, tmode, add&&(d==dim-1), 85dfe03796SJeremy L Thompson d==0?u:tmp[d%2], 86dfe03796SJeremy L Thompson d==dim-1?v:tmp[(d+1)%2]); 87*e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 8821617c04Sjeremylt pre /= P; 8921617c04Sjeremylt post *= Q; 9021617c04Sjeremylt } 91dfe03796SJeremy L Thompson } 92a2b73c81Sjeremylt } break; 938d94b059Sjeremylt // Evaluate the gradient to/from quadrature points 94a2b73c81Sjeremylt case CEED_EVAL_GRAD: { 9521617c04Sjeremylt // In CEED_NOTRANSPOSE mode: 96ecf6354eSJed Brown // u has shape [dim, ncomp, P^dim, nelem], row-major layout 97ecf6354eSJed Brown // v has shape [dim, ncomp, Q^dim, nelem], row-major layout 9821617c04Sjeremylt // In CEED_TRANSPOSE mode, the sizes of u and v are switched. 9984a01de5SJeremy L Thompson CeedInt P = P1d, Q = Q1d; 10021617c04Sjeremylt if (tmode == CEED_TRANSPOSE) { 10184a01de5SJeremy L Thompson P = Q1d, Q = Q1d; 10221617c04Sjeremylt } 10384a01de5SJeremy L Thompson CeedBasis_Ref *impl; 104*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetData(basis, &impl); CeedChkBackend(ierr); 10584a01de5SJeremy L Thompson CeedInt pre = ncomp*CeedIntPow(P, dim-1), post = nelem; 1066c58de82SJeremy L Thompson const CeedScalar *interp1d; 107*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetInterp1D(basis, &interp1d); CeedChkBackend(ierr); 108dfe03796SJeremy L Thompson if (impl->collograd1d) { 109a7bd39daSjeremylt CeedScalar tmp[2][nelem*ncomp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 110a7bd39daSjeremylt CeedScalar interp[nelem*ncomp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 11184a01de5SJeremy L Thompson // Interpolate to quadrature points (NoTranspose) 11284a01de5SJeremy L Thompson // or Grad to quadrature points (Transpose) 11321617c04Sjeremylt for (CeedInt d=0; d<dim; d++) { 1142f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 11584a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 11684a01de5SJeremy L Thompson ? interp1d 117dfe03796SJeremy L Thompson : impl->collograd1d), 11884a01de5SJeremy L Thompson tmode, add&&(d>0), 11984a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 12084a01de5SJeremy L Thompson ? (d==0?u:tmp[d%2]) 12184a01de5SJeremy L Thompson : u + d*nqpt*ncomp*nelem), 12284a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 12384a01de5SJeremy L Thompson ? (d==dim-1?interp:tmp[(d+1)%2]) 12484a01de5SJeremy L Thompson : interp)); 125*e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 12621617c04Sjeremylt pre /= P; 12721617c04Sjeremylt post *= Q; 12821617c04Sjeremylt } 12984a01de5SJeremy L Thompson // Grad to quadrature points (NoTranspose) 1308795c945Sjeremylt // or Interpolate to nodes (Transpose) 13184a01de5SJeremy L Thompson P = Q1d, Q = Q1d; 13284a01de5SJeremy L Thompson if (tmode == CEED_TRANSPOSE) { 13384a01de5SJeremy L Thompson P = Q1d, Q = P1d; 13484a01de5SJeremy L Thompson } 13584a01de5SJeremy L Thompson pre = ncomp*CeedIntPow(P, dim-1), post = nelem; 13684a01de5SJeremy L Thompson for (CeedInt d=0; d<dim; d++) { 1372f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 13884a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 139dfe03796SJeremy L Thompson ? impl->collograd1d 14084a01de5SJeremy L Thompson : interp1d), 14184a01de5SJeremy L Thompson tmode, add&&(d==dim-1), 14284a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 14384a01de5SJeremy L Thompson ? interp 14484a01de5SJeremy L Thompson : (d==0?interp:tmp[d%2])), 14584a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 14684a01de5SJeremy L Thompson ? v + d*nqpt*ncomp*nelem 14784a01de5SJeremy L Thompson : (d==dim-1?v:tmp[(d+1)%2]))); 148*e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 14984a01de5SJeremy L Thompson pre /= P; 15084a01de5SJeremy L Thompson post *= Q; 15121617c04Sjeremylt } 152dfe03796SJeremy L Thompson } else if (impl->collointerp) { // Qpts collocated with nodes 1536c58de82SJeremy L Thompson const CeedScalar *grad1d; 154*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetGrad1D(basis, &grad1d); CeedChkBackend(ierr); 155dfe03796SJeremy L Thompson 156dfe03796SJeremy L Thompson // Dim contractions, identity in other directions 157dfe03796SJeremy L Thompson CeedInt pre = ncomp*CeedIntPow(P, dim-1), post = nelem; 158c6158135Sjeremylt for (CeedInt d=0; d<dim; d++) { 159dfe03796SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 160a1dbd226Sjeremylt grad1d, tmode, add&&(d>0), 161dfe03796SJeremy L Thompson tmode == CEED_NOTRANSPOSE 162dfe03796SJeremy L Thompson ? u : u+d*ncomp*nqpt*nelem, 163dfe03796SJeremy L Thompson tmode == CEED_TRANSPOSE 164dfe03796SJeremy L Thompson ? v : v+d*ncomp*nqpt*nelem); 165*e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 166c6158135Sjeremylt pre /= P; 167c6158135Sjeremylt post *= Q; 168dfe03796SJeremy L Thompson } 169a7bd39daSjeremylt } else { // Underintegration, P > Q 1706c58de82SJeremy L Thompson const CeedScalar *grad1d; 171*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetGrad1D(basis, &grad1d); CeedChkBackend(ierr); 172a7bd39daSjeremylt 173a7bd39daSjeremylt if (tmode == CEED_TRANSPOSE) { 174a7bd39daSjeremylt P = Q1d, Q = P1d; 175a7bd39daSjeremylt } 176a7bd39daSjeremylt CeedScalar tmp[2][nelem*ncomp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 177a7bd39daSjeremylt 178a7bd39daSjeremylt // Dim**2 contractions, apply grad when pass == dim 179a7bd39daSjeremylt for (CeedInt p=0; p<dim; p++) { 180a7bd39daSjeremylt CeedInt pre = ncomp*CeedIntPow(P, dim-1), post = nelem; 181a7bd39daSjeremylt for (CeedInt d=0; d<dim; d++) { 182a7bd39daSjeremylt ierr = CeedTensorContractApply(contract, pre, P, post, Q, 183a7bd39daSjeremylt (p==d)? grad1d : interp1d, 184a7bd39daSjeremylt tmode, add&&(d==dim-1), 185a7bd39daSjeremylt (d == 0 186a7bd39daSjeremylt ? (tmode == CEED_NOTRANSPOSE 187a7bd39daSjeremylt ? u : u+p*ncomp*nqpt*nelem) 188a7bd39daSjeremylt : tmp[d%2]), 189a7bd39daSjeremylt (d == dim-1 190a7bd39daSjeremylt ? (tmode == CEED_TRANSPOSE 191a7bd39daSjeremylt ? v : v+p*ncomp*nqpt*nelem) 192a7bd39daSjeremylt : tmp[(d+1)%2])); 193*e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 194a7bd39daSjeremylt pre /= P; 195a7bd39daSjeremylt post *= Q; 196a7bd39daSjeremylt } 197a7bd39daSjeremylt } 198a7bd39daSjeremylt } 199a2b73c81Sjeremylt } break; 2008d94b059Sjeremylt // Retrieve interpolation weights 201a2b73c81Sjeremylt case CEED_EVAL_WEIGHT: { 20221617c04Sjeremylt if (tmode == CEED_TRANSPOSE) 203c042f62fSJeremy L Thompson // LCOV_EXCL_START 204*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 20521617c04Sjeremylt "CEED_EVAL_WEIGHT incompatible with CEED_TRANSPOSE"); 206c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 2074ce2993fSjeremylt CeedInt Q = Q1d; 2086c58de82SJeremy L Thompson const CeedScalar *qweight1d; 209*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetQWeights(basis, &qweight1d); CeedChkBackend(ierr); 21021617c04Sjeremylt for (CeedInt d=0; d<dim; d++) { 211b5cf12eeSjeremylt CeedInt pre = CeedIntPow(Q, dim-d-1), post = CeedIntPow(Q, d); 212a2b73c81Sjeremylt for (CeedInt i=0; i<pre; i++) 213a2b73c81Sjeremylt for (CeedInt j=0; j<Q; j++) 21484a01de5SJeremy L Thompson for (CeedInt k=0; k<post; k++) { 21584a01de5SJeremy L Thompson CeedScalar w = qweight1d[j] 21684a01de5SJeremy L Thompson * (d == 0 ? 1 : v[((i*Q + j)*post + k)*nelem]); 21784a01de5SJeremy L Thompson for (CeedInt e=0; e<nelem; e++) 21884a01de5SJeremy L Thompson v[((i*Q + j)*post + k)*nelem + e] = w; 21984a01de5SJeremy L Thompson } 22021617c04Sjeremylt } 221a2b73c81Sjeremylt } break; 222c042f62fSJeremy L Thompson // LCOV_EXCL_START 2238d94b059Sjeremylt // Evaluate the divergence to/from the quadrature points 224a2b73c81Sjeremylt case CEED_EVAL_DIV: 225*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "CEED_EVAL_DIV not supported"); 2268d94b059Sjeremylt // Evaluate the curl to/from the quadrature points 227a2b73c81Sjeremylt case CEED_EVAL_CURL: 228*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "CEED_EVAL_CURL not supported"); 2298d94b059Sjeremylt // Take no action, BasisApply should not have been called 230a2b73c81Sjeremylt case CEED_EVAL_NONE: 231*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 2324b8bea3bSJed Brown "CEED_EVAL_NONE does not make sense in this context"); 233c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 23421617c04Sjeremylt } 235a8de75f0Sjeremylt } else { 236a8de75f0Sjeremylt // Non-tensor basis 237a8de75f0Sjeremylt switch (emode) { 23884a01de5SJeremy L Thompson // Interpolate to/from quadrature points 239a8de75f0Sjeremylt case CEED_EVAL_INTERP: { 2408795c945Sjeremylt CeedInt P = nnodes, Q = nqpt; 2416c58de82SJeremy L Thompson const CeedScalar *interp; 242*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetInterp(basis, &interp); CeedChkBackend(ierr); 243a8de75f0Sjeremylt if (tmode == CEED_TRANSPOSE) { 2448795c945Sjeremylt P = nqpt; Q = nnodes; 245a8de75f0Sjeremylt } 2462f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, ncomp, P, nelem, Q, 24784a01de5SJeremy L Thompson interp, tmode, add, u, v); 248*e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 249a8de75f0Sjeremylt } 250a8de75f0Sjeremylt break; 25184a01de5SJeremy L Thompson // Evaluate the gradient to/from quadrature points 252a8de75f0Sjeremylt case CEED_EVAL_GRAD: { 253475a782bSnbeams CeedInt P = nnodes, Q = nqpt; 254475a782bSnbeams CeedInt dimstride = nqpt * ncomp * nelem; 255475a782bSnbeams CeedInt gradstride = nqpt * nnodes; 2566c58de82SJeremy L Thompson const CeedScalar *grad; 257*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetGrad(basis, &grad); CeedChkBackend(ierr); 258a8de75f0Sjeremylt if (tmode == CEED_TRANSPOSE) { 259475a782bSnbeams P = nqpt; Q = nnodes; 260475a782bSnbeams for (CeedInt d = 0; d < dim; d++) { 2612f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, ncomp, P, nelem, Q, 262475a782bSnbeams grad + d * gradstride, tmode, add, 263*e15f9bd0SJeremy L Thompson u + d * dimstride, v); CeedChkBackend(ierr); 264475a782bSnbeams } 265475a782bSnbeams } else { 266475a782bSnbeams for (CeedInt d = 0; d < dim; d++) { 267475a782bSnbeams ierr = CeedTensorContractApply(contract, ncomp, P, nelem, Q, 268475a782bSnbeams grad + d * gradstride, tmode, add, 269*e15f9bd0SJeremy L Thompson u, v + d * dimstride); CeedChkBackend(ierr); 270475a782bSnbeams } 271475a782bSnbeams } 272a8de75f0Sjeremylt } 273a8de75f0Sjeremylt break; 27484a01de5SJeremy L Thompson // Retrieve interpolation weights 275a8de75f0Sjeremylt case CEED_EVAL_WEIGHT: { 276a8de75f0Sjeremylt if (tmode == CEED_TRANSPOSE) 277c042f62fSJeremy L Thompson // LCOV_EXCL_START 278*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 279a8de75f0Sjeremylt "CEED_EVAL_WEIGHT incompatible with CEED_TRANSPOSE"); 280c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 2816c58de82SJeremy L Thompson const CeedScalar *qweight; 282*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetQWeights(basis, &qweight); CeedChkBackend(ierr); 283a8de75f0Sjeremylt for (CeedInt i=0; i<nqpt; i++) 28484a01de5SJeremy L Thompson for (CeedInt e=0; e<nelem; e++) 28584a01de5SJeremy L Thompson v[i*nelem + e] = qweight[i]; 286a8de75f0Sjeremylt } break; 287c042f62fSJeremy L Thompson // LCOV_EXCL_START 28884a01de5SJeremy L Thompson // Evaluate the divergence to/from the quadrature points 289a8de75f0Sjeremylt case CEED_EVAL_DIV: 290*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "CEED_EVAL_DIV not supported"); 29184a01de5SJeremy L Thompson // Evaluate the curl to/from the quadrature points 292a8de75f0Sjeremylt case CEED_EVAL_CURL: 293*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "CEED_EVAL_CURL not supported"); 29484a01de5SJeremy L Thompson // Take no action, BasisApply should not have been called 295a8de75f0Sjeremylt case CEED_EVAL_NONE: 296*e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 297a8de75f0Sjeremylt "CEED_EVAL_NONE does not make sense in this context"); 298c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 299a8de75f0Sjeremylt } 300a8de75f0Sjeremylt } 301a7b7f929Sjeremylt if (U != CEED_VECTOR_NONE) { 302*e15f9bd0SJeremy L Thompson ierr = CeedVectorRestoreArrayRead(U, &u); CeedChkBackend(ierr); 303aedaa0e5Sjeremylt } 304*e15f9bd0SJeremy L Thompson ierr = CeedVectorRestoreArray(V, &v); CeedChkBackend(ierr); 305*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 30621617c04Sjeremylt } 30721617c04Sjeremylt 308f10650afSjeremylt //------------------------------------------------------------------------------ 309f10650afSjeremylt // Basis Destroy Non-Tensor 310f10650afSjeremylt //------------------------------------------------------------------------------ 31184a01de5SJeremy L Thompson static int CeedBasisDestroyNonTensor_Ref(CeedBasis basis) { 3122f86a920SJeremy L Thompson int ierr; 3132f86a920SJeremy L Thompson CeedTensorContract contract; 314*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetTensorContract(basis, &contract); CeedChkBackend(ierr); 315*e15f9bd0SJeremy L Thompson ierr = CeedTensorContractDestroy(&contract); CeedChkBackend(ierr); 316*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 31784a01de5SJeremy L Thompson } 31884a01de5SJeremy L Thompson 319f10650afSjeremylt //------------------------------------------------------------------------------ 320f10650afSjeremylt // Basis Create Non-Tensor 321f10650afSjeremylt //------------------------------------------------------------------------------ 322f10650afSjeremylt int CeedBasisCreateH1_Ref(CeedElemTopology topo, CeedInt dim, 323f10650afSjeremylt CeedInt nnodes, CeedInt nqpts, 324f10650afSjeremylt const CeedScalar *interp, 325f10650afSjeremylt const CeedScalar *grad, 326f10650afSjeremylt const CeedScalar *qref, 327f10650afSjeremylt const CeedScalar *qweight, 328f10650afSjeremylt CeedBasis basis) { 329f10650afSjeremylt int ierr; 330f10650afSjeremylt Ceed ceed; 331*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetCeed(basis, &ceed); CeedChkBackend(ierr); 332f10650afSjeremylt 333f10650afSjeremylt Ceed parent; 334*e15f9bd0SJeremy L Thompson ierr = CeedGetParent(ceed, &parent); CeedChkBackend(ierr); 335f10650afSjeremylt CeedTensorContract contract; 336*e15f9bd0SJeremy L Thompson ierr = CeedTensorContractCreate(parent, basis, &contract); CeedChkBackend(ierr); 337*e15f9bd0SJeremy L Thompson ierr = CeedBasisSetTensorContract(basis, &contract); CeedChkBackend(ierr); 338f10650afSjeremylt 339f10650afSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Apply", 340*e15f9bd0SJeremy L Thompson CeedBasisApply_Ref); CeedChkBackend(ierr); 341f10650afSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Destroy", 342*e15f9bd0SJeremy L Thompson CeedBasisDestroyNonTensor_Ref); CeedChkBackend(ierr); 343f10650afSjeremylt 344*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 345f10650afSjeremylt } 346f10650afSjeremylt 347f10650afSjeremylt //------------------------------------------------------------------------------ 348f10650afSjeremylt // Basis Destroy Tensor 349f10650afSjeremylt //------------------------------------------------------------------------------ 35084a01de5SJeremy L Thompson static int CeedBasisDestroyTensor_Ref(CeedBasis basis) { 35184a01de5SJeremy L Thompson int ierr; 3522f86a920SJeremy L Thompson CeedTensorContract contract; 353*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetTensorContract(basis, &contract); CeedChkBackend(ierr); 354*e15f9bd0SJeremy L Thompson ierr = CeedTensorContractDestroy(&contract); CeedChkBackend(ierr); 3552f86a920SJeremy L Thompson 35684a01de5SJeremy L Thompson CeedBasis_Ref *impl; 357*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetData(basis, &impl); CeedChkBackend(ierr); 358*e15f9bd0SJeremy L Thompson ierr = CeedFree(&impl->collograd1d); CeedChkBackend(ierr); 359*e15f9bd0SJeremy L Thompson ierr = CeedFree(&impl); CeedChkBackend(ierr); 36084a01de5SJeremy L Thompson 361*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 36221617c04Sjeremylt } 36321617c04Sjeremylt 364f10650afSjeremylt //------------------------------------------------------------------------------ 365f10650afSjeremylt // Basis Create Tensor 366f10650afSjeremylt //------------------------------------------------------------------------------ 367667bc5fcSjeremylt int CeedBasisCreateTensorH1_Ref(CeedInt dim, CeedInt P1d, 36821617c04Sjeremylt CeedInt Q1d, const CeedScalar *interp1d, 36921617c04Sjeremylt const CeedScalar *grad1d, 37021617c04Sjeremylt const CeedScalar *qref1d, 37121617c04Sjeremylt const CeedScalar *qweight1d, 37221617c04Sjeremylt CeedBasis basis) { 373fe2413ffSjeremylt int ierr; 374fe2413ffSjeremylt Ceed ceed; 375*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetCeed(basis, &ceed); CeedChkBackend(ierr); 37684a01de5SJeremy L Thompson CeedBasis_Ref *impl; 377*e15f9bd0SJeremy L Thompson ierr = CeedCalloc(1, &impl); CeedChkBackend(ierr); 378dfe03796SJeremy L Thompson // Check for collocated interp 379dfe03796SJeremy L Thompson if (Q1d == P1d) { 380dfe03796SJeremy L Thompson bool collocated = 1; 381dfe03796SJeremy L Thompson for (CeedInt i=0; i<P1d; i++) { 382dfe03796SJeremy L Thompson collocated = collocated && (fabs(interp1d[i+P1d*i] - 1.0) < 1e-14); 383dfe03796SJeremy L Thompson for (CeedInt j=0; j<P1d; j++) 384dfe03796SJeremy L Thompson if (j != i) 385dfe03796SJeremy L Thompson collocated = collocated && (fabs(interp1d[j+P1d*i]) < 1e-14); 386dfe03796SJeremy L Thompson } 387dfe03796SJeremy L Thompson impl->collointerp = collocated; 388dfe03796SJeremy L Thompson } 389dfe03796SJeremy L Thompson // Calculate collocated grad 390dfe03796SJeremy L Thompson if (Q1d >= P1d && !impl->collointerp) { 391*e15f9bd0SJeremy L Thompson ierr = CeedMalloc(Q1d*Q1d, &impl->collograd1d); CeedChkBackend(ierr); 392*e15f9bd0SJeremy L Thompson ierr = CeedBasisGetCollocatedGrad(basis, impl->collograd1d); 393*e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 394a7bd39daSjeremylt } 395*e15f9bd0SJeremy L Thompson ierr = CeedBasisSetData(basis, impl); CeedChkBackend(ierr); 396fe2413ffSjeremylt 3972f86a920SJeremy L Thompson Ceed parent; 398*e15f9bd0SJeremy L Thompson ierr = CeedGetParent(ceed, &parent); CeedChkBackend(ierr); 3992f86a920SJeremy L Thompson CeedTensorContract contract; 400*e15f9bd0SJeremy L Thompson ierr = CeedTensorContractCreate(parent, basis, &contract); CeedChkBackend(ierr); 401*e15f9bd0SJeremy L Thompson ierr = CeedBasisSetTensorContract(basis, &contract); CeedChkBackend(ierr); 4022f86a920SJeremy L Thompson 403fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Apply", 404*e15f9bd0SJeremy L Thompson CeedBasisApply_Ref); CeedChkBackend(ierr); 405fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Destroy", 406*e15f9bd0SJeremy L Thompson CeedBasisDestroyTensor_Ref); CeedChkBackend(ierr); 407*e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 40821617c04Sjeremylt } 409a8de75f0Sjeremylt 410f10650afSjeremylt //------------------------------------------------------------------------------ 411