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 <string.h> 1821617c04Sjeremylt #include "ceed-ref.h" 1921617c04Sjeremylt 20d3181881Sjeremylt static int CeedBasisApply_Ref(CeedBasis basis, CeedInt nelem, 21d3181881Sjeremylt CeedTransposeMode tmode, CeedEvalMode emode, 22aedaa0e5Sjeremylt CeedVector U, CeedVector V) { 2321617c04Sjeremylt int ierr; 244ce2993fSjeremylt Ceed ceed; 254ce2993fSjeremylt ierr = CeedBasisGetCeed(basis, &ceed); CeedChk(ierr); 264ce2993fSjeremylt CeedInt dim, ncomp, ndof, nqpt; 274ce2993fSjeremylt ierr = CeedBasisGetDimension(basis, &dim); CeedChk(ierr); 284ce2993fSjeremylt ierr = CeedBasisGetNumComponents(basis, &ncomp); CeedChk(ierr); 29a8de75f0Sjeremylt ierr = CeedBasisGetNumNodes(basis, &ndof); CeedChk(ierr); 304ce2993fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis, &nqpt); CeedChk(ierr); 31*2f86a920SJeremy L Thompson CeedTensorContract contract; 32*2f86a920SJeremy L Thompson ierr = CeedBasisGetTensorContract(basis, &contract); CeedChk(ierr); 3321617c04Sjeremylt const CeedInt add = (tmode == CEED_TRANSPOSE); 34aedaa0e5Sjeremylt const CeedScalar *u; 35aedaa0e5Sjeremylt CeedScalar *v; 36aedaa0e5Sjeremylt if (U) { 37aedaa0e5Sjeremylt ierr = CeedVectorGetArrayRead(U, CEED_MEM_HOST, &u); CeedChk(ierr); 38aedaa0e5Sjeremylt } else if (emode != CEED_EVAL_WEIGHT) { 39aedaa0e5Sjeremylt return CeedError(ceed, 1, 40aedaa0e5Sjeremylt "An input vector is required for this CeedEvalMode"); 41aedaa0e5Sjeremylt } 42aedaa0e5Sjeremylt ierr = CeedVectorGetArray(V, CEED_MEM_HOST, &v); CeedChk(ierr); 4321617c04Sjeremylt 448d94b059Sjeremylt // Clear v if operating in transpose 4521617c04Sjeremylt if (tmode == CEED_TRANSPOSE) { 4684a01de5SJeremy L Thompson const CeedInt vsize = nelem*ncomp*ndof; 4721617c04Sjeremylt for (CeedInt i = 0; i < vsize; i++) 4884a01de5SJeremy L Thompson v[i] = (CeedScalar) 0.0; 4921617c04Sjeremylt } 504ce2993fSjeremylt bool tensorbasis; 514ce2993fSjeremylt ierr = CeedBasisGetTensorStatus(basis, &tensorbasis); CeedChk(ierr); 5284a01de5SJeremy L Thompson // Tensor basis 534ce2993fSjeremylt if (tensorbasis) { 544ce2993fSjeremylt CeedInt P1d, Q1d; 554ce2993fSjeremylt ierr = CeedBasisGetNumNodes1D(basis, &P1d); CeedChk(ierr); 564ce2993fSjeremylt ierr = CeedBasisGetNumQuadraturePoints1D(basis, &Q1d); CeedChk(ierr); 57a2b73c81Sjeremylt switch (emode) { 588d94b059Sjeremylt // Interpolate to/from quadrature points 59a2b73c81Sjeremylt case CEED_EVAL_INTERP: { 604ce2993fSjeremylt CeedInt P = P1d, Q = Q1d; 6121617c04Sjeremylt if (tmode == CEED_TRANSPOSE) { 624ce2993fSjeremylt P = Q1d; Q = P1d; 6321617c04Sjeremylt } 6484a01de5SJeremy L Thompson CeedInt pre = ncomp*CeedIntPow(P, dim-1), post = nelem; 6584a01de5SJeremy L Thompson CeedScalar tmp[2][nelem*ncomp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 664ce2993fSjeremylt CeedScalar *interp1d; 674ce2993fSjeremylt ierr = CeedBasisGetInterp(basis, &interp1d); CeedChk(ierr); 6821617c04Sjeremylt for (CeedInt d=0; d<dim; d++) { 69*2f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 7084a01de5SJeremy L Thompson interp1d, tmode, add&&(d==dim-1), 7121617c04Sjeremylt d==0?u:tmp[d%2], d==dim-1?v:tmp[(d+1)%2]); 7221617c04Sjeremylt CeedChk(ierr); 7321617c04Sjeremylt pre /= P; 7421617c04Sjeremylt post *= Q; 7521617c04Sjeremylt } 76a2b73c81Sjeremylt } break; 778d94b059Sjeremylt // Evaluate the gradient to/from quadrature points 78a2b73c81Sjeremylt case CEED_EVAL_GRAD: { 7921617c04Sjeremylt // In CEED_NOTRANSPOSE mode: 80ecf6354eSJed Brown // u has shape [dim, ncomp, P^dim, nelem], row-major layout 81ecf6354eSJed Brown // v has shape [dim, ncomp, Q^dim, nelem], row-major layout 8221617c04Sjeremylt // In CEED_TRANSPOSE mode, the sizes of u and v are switched. 8384a01de5SJeremy L Thompson CeedInt P = P1d, Q = Q1d; 8421617c04Sjeremylt if (tmode == CEED_TRANSPOSE) { 8584a01de5SJeremy L Thompson P = Q1d, Q = Q1d; 8621617c04Sjeremylt } 8784a01de5SJeremy L Thompson CeedBasis_Ref *impl; 8884a01de5SJeremy L Thompson ierr = CeedBasisGetData(basis, (void *)&impl); CeedChk(ierr); 8984a01de5SJeremy L Thompson CeedScalar interp[nelem*ncomp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 9084a01de5SJeremy L Thompson CeedInt pre = ncomp*CeedIntPow(P, dim-1), post = nelem; 9184a01de5SJeremy L Thompson CeedScalar tmp[2][nelem*ncomp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 9284a01de5SJeremy L Thompson CeedScalar *interp1d; 934ce2993fSjeremylt ierr = CeedBasisGetInterp(basis, &interp1d); CeedChk(ierr); 9484a01de5SJeremy L Thompson // Interpolate to quadrature points (NoTranspose) 9584a01de5SJeremy L Thompson // or Grad to quadrature points (Transpose) 9621617c04Sjeremylt for (CeedInt d=0; d<dim; d++) { 97*2f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 9884a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 9984a01de5SJeremy L Thompson ? interp1d 10084a01de5SJeremy L Thompson : impl->colograd1d), 10184a01de5SJeremy L Thompson tmode, add&&(d>0), 10284a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 10384a01de5SJeremy L Thompson ? (d==0?u:tmp[d%2]) 10484a01de5SJeremy L Thompson : u + d*nqpt*ncomp*nelem), 10584a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 10684a01de5SJeremy L Thompson ? (d==dim-1?interp:tmp[(d+1)%2]) 10784a01de5SJeremy L Thompson : interp)); 10821617c04Sjeremylt CeedChk(ierr); 10921617c04Sjeremylt pre /= P; 11021617c04Sjeremylt post *= Q; 11121617c04Sjeremylt } 11284a01de5SJeremy L Thompson // Grad to quadrature points (NoTranspose) 11384a01de5SJeremy L Thompson // or Interpolate to dofs (Transpose) 11484a01de5SJeremy L Thompson P = Q1d, Q = Q1d; 11584a01de5SJeremy L Thompson if (tmode == CEED_TRANSPOSE) { 11684a01de5SJeremy L Thompson P = Q1d, Q = P1d; 11784a01de5SJeremy L Thompson } 11884a01de5SJeremy L Thompson pre = ncomp*CeedIntPow(P, dim-1), post = nelem; 11984a01de5SJeremy L Thompson for (CeedInt d=0; d<dim; d++) { 120*2f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 12184a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 12284a01de5SJeremy L Thompson ? impl->colograd1d 12384a01de5SJeremy L Thompson : interp1d), 12484a01de5SJeremy L Thompson tmode, add&&(d==dim-1), 12584a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 12684a01de5SJeremy L Thompson ? interp 12784a01de5SJeremy L Thompson : (d==0?interp:tmp[d%2])), 12884a01de5SJeremy L Thompson (tmode == CEED_NOTRANSPOSE 12984a01de5SJeremy L Thompson ? v + d*nqpt*ncomp*nelem 13084a01de5SJeremy L Thompson : (d==dim-1?v:tmp[(d+1)%2]))); 13184a01de5SJeremy L Thompson CeedChk(ierr); 13284a01de5SJeremy L Thompson pre /= P; 13384a01de5SJeremy L Thompson post *= Q; 13421617c04Sjeremylt } 135a2b73c81Sjeremylt } break; 1368d94b059Sjeremylt // Retrieve interpolation weights 137a2b73c81Sjeremylt case CEED_EVAL_WEIGHT: { 13821617c04Sjeremylt if (tmode == CEED_TRANSPOSE) 1394ce2993fSjeremylt return CeedError(ceed, 1, 14021617c04Sjeremylt "CEED_EVAL_WEIGHT incompatible with CEED_TRANSPOSE"); 1414ce2993fSjeremylt CeedInt Q = Q1d; 1424ce2993fSjeremylt CeedScalar *qweight1d; 1434ce2993fSjeremylt ierr = CeedBasisGetQWeights(basis, &qweight1d); CeedChk(ierr); 14421617c04Sjeremylt for (CeedInt d=0; d<dim; d++) { 145b5cf12eeSjeremylt CeedInt pre = CeedIntPow(Q, dim-d-1), post = CeedIntPow(Q, d); 146a2b73c81Sjeremylt for (CeedInt i=0; i<pre; i++) 147a2b73c81Sjeremylt for (CeedInt j=0; j<Q; j++) 14884a01de5SJeremy L Thompson for (CeedInt k=0; k<post; k++) { 14984a01de5SJeremy L Thompson CeedScalar w = qweight1d[j] 15084a01de5SJeremy L Thompson * (d == 0 ? 1 : v[((i*Q + j)*post + k)*nelem]); 15184a01de5SJeremy L Thompson for (CeedInt e=0; e<nelem; e++) 15284a01de5SJeremy L Thompson v[((i*Q + j)*post + k)*nelem + e] = w; 15384a01de5SJeremy L Thompson } 15421617c04Sjeremylt } 155a2b73c81Sjeremylt } break; 1568d94b059Sjeremylt // Evaluate the divergence to/from the quadrature points 157a2b73c81Sjeremylt case CEED_EVAL_DIV: 1584ce2993fSjeremylt return CeedError(ceed, 1, "CEED_EVAL_DIV not supported"); 1598d94b059Sjeremylt // Evaluate the curl to/from the quadrature points 160a2b73c81Sjeremylt case CEED_EVAL_CURL: 1614ce2993fSjeremylt return CeedError(ceed, 1, "CEED_EVAL_CURL not supported"); 1628d94b059Sjeremylt // Take no action, BasisApply should not have been called 163a2b73c81Sjeremylt case CEED_EVAL_NONE: 1644ce2993fSjeremylt return CeedError(ceed, 1, 1654b8bea3bSJed Brown "CEED_EVAL_NONE does not make sense in this context"); 16621617c04Sjeremylt } 167a8de75f0Sjeremylt } else { 168a8de75f0Sjeremylt // Non-tensor basis 169a8de75f0Sjeremylt switch (emode) { 17084a01de5SJeremy L Thompson // Interpolate to/from quadrature points 171a8de75f0Sjeremylt case CEED_EVAL_INTERP: { 1724ce2993fSjeremylt CeedInt P = ndof, Q = nqpt; 1734ce2993fSjeremylt CeedScalar *interp; 1744ce2993fSjeremylt ierr = CeedBasisGetInterp(basis, &interp); CeedChk(ierr); 175a8de75f0Sjeremylt if (tmode == CEED_TRANSPOSE) { 1764ce2993fSjeremylt P = nqpt; Q = ndof; 177a8de75f0Sjeremylt } 178*2f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, ncomp, P, nelem, Q, 17984a01de5SJeremy L Thompson interp, tmode, add, u, v); 180a8de75f0Sjeremylt CeedChk(ierr); 181a8de75f0Sjeremylt } 182a8de75f0Sjeremylt break; 18384a01de5SJeremy L Thompson // Evaluate the gradient to/from quadrature points 184a8de75f0Sjeremylt case CEED_EVAL_GRAD: { 1854ce2993fSjeremylt CeedInt P = ndof, Q = dim*nqpt; 1864ce2993fSjeremylt CeedScalar *grad; 1874ce2993fSjeremylt ierr = CeedBasisGetGrad(basis, &grad); CeedChk(ierr); 188a8de75f0Sjeremylt if (tmode == CEED_TRANSPOSE) { 1894ce2993fSjeremylt P = dim*nqpt; Q = ndof; 190a8de75f0Sjeremylt } 191*2f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, ncomp, P, nelem, Q, 19284a01de5SJeremy L Thompson grad, tmode, add, u, v); 193a8de75f0Sjeremylt CeedChk(ierr); 194a8de75f0Sjeremylt } 195a8de75f0Sjeremylt break; 19684a01de5SJeremy L Thompson // Retrieve interpolation weights 197a8de75f0Sjeremylt case CEED_EVAL_WEIGHT: { 198a8de75f0Sjeremylt if (tmode == CEED_TRANSPOSE) 1994ce2993fSjeremylt return CeedError(ceed, 1, 200a8de75f0Sjeremylt "CEED_EVAL_WEIGHT incompatible with CEED_TRANSPOSE"); 2014ce2993fSjeremylt CeedScalar *qweight; 2024ce2993fSjeremylt ierr = CeedBasisGetQWeights(basis, &qweight); CeedChk(ierr); 203a8de75f0Sjeremylt for (CeedInt i=0; i<nqpt; i++) 20484a01de5SJeremy L Thompson for (CeedInt e=0; e<nelem; e++) 20584a01de5SJeremy L Thompson v[i*nelem + e] = qweight[i]; 206a8de75f0Sjeremylt } break; 20784a01de5SJeremy L Thompson // Evaluate the divergence to/from the quadrature points 208a8de75f0Sjeremylt case CEED_EVAL_DIV: 2094ce2993fSjeremylt return CeedError(ceed, 1, "CEED_EVAL_DIV not supported"); 21084a01de5SJeremy L Thompson // Evaluate the curl to/from the quadrature points 211a8de75f0Sjeremylt case CEED_EVAL_CURL: 2124ce2993fSjeremylt return CeedError(ceed, 1, "CEED_EVAL_CURL not supported"); 21384a01de5SJeremy L Thompson // Take no action, BasisApply should not have been called 214a8de75f0Sjeremylt case CEED_EVAL_NONE: 2154ce2993fSjeremylt return CeedError(ceed, 1, 216a8de75f0Sjeremylt "CEED_EVAL_NONE does not make sense in this context"); 217a8de75f0Sjeremylt } 218a8de75f0Sjeremylt } 219aedaa0e5Sjeremylt if (U) { 220aedaa0e5Sjeremylt ierr = CeedVectorRestoreArrayRead(U, &u); CeedChk(ierr); 221aedaa0e5Sjeremylt } 222aedaa0e5Sjeremylt ierr = CeedVectorRestoreArray(V, &v); CeedChk(ierr); 22321617c04Sjeremylt return 0; 22421617c04Sjeremylt } 22521617c04Sjeremylt 22684a01de5SJeremy L Thompson static int CeedBasisDestroyNonTensor_Ref(CeedBasis basis) { 227*2f86a920SJeremy L Thompson int ierr; 228*2f86a920SJeremy L Thompson CeedTensorContract contract; 229*2f86a920SJeremy L Thompson ierr = CeedBasisGetTensorContract(basis, &contract); CeedChk(ierr); 230*2f86a920SJeremy L Thompson ierr = CeedTensorContractDestroy(&contract); CeedChk(ierr); 23184a01de5SJeremy L Thompson return 0; 23284a01de5SJeremy L Thompson } 23384a01de5SJeremy L Thompson 23484a01de5SJeremy L Thompson static int CeedBasisDestroyTensor_Ref(CeedBasis basis) { 23584a01de5SJeremy L Thompson int ierr; 236*2f86a920SJeremy L Thompson CeedTensorContract contract; 237*2f86a920SJeremy L Thompson ierr = CeedBasisGetTensorContract(basis, &contract); CeedChk(ierr); 238*2f86a920SJeremy L Thompson ierr = CeedTensorContractDestroy(&contract); CeedChk(ierr); 239*2f86a920SJeremy L Thompson 24084a01de5SJeremy L Thompson CeedBasis_Ref *impl; 24184a01de5SJeremy L Thompson ierr = CeedBasisGetData(basis, (void *)&impl); CeedChk(ierr); 24284a01de5SJeremy L Thompson ierr = CeedFree(&impl->colograd1d); CeedChk(ierr); 24384a01de5SJeremy L Thompson ierr = CeedFree(&impl); CeedChk(ierr); 24484a01de5SJeremy L Thompson 24521617c04Sjeremylt return 0; 24621617c04Sjeremylt } 24721617c04Sjeremylt 248667bc5fcSjeremylt int CeedBasisCreateTensorH1_Ref(CeedInt dim, CeedInt P1d, 24921617c04Sjeremylt CeedInt Q1d, const CeedScalar *interp1d, 25021617c04Sjeremylt const CeedScalar *grad1d, 25121617c04Sjeremylt const CeedScalar *qref1d, 25221617c04Sjeremylt const CeedScalar *qweight1d, 25321617c04Sjeremylt CeedBasis basis) { 254fe2413ffSjeremylt int ierr; 255fe2413ffSjeremylt Ceed ceed; 256fe2413ffSjeremylt ierr = CeedBasisGetCeed(basis, &ceed); CeedChk(ierr); 25784a01de5SJeremy L Thompson CeedBasis_Ref *impl; 25884a01de5SJeremy L Thompson ierr = CeedCalloc(1, &impl); CeedChk(ierr); 25984a01de5SJeremy L Thompson ierr = CeedMalloc(Q1d*Q1d, &impl->colograd1d); CeedChk(ierr); 26084a01de5SJeremy L Thompson ierr = CeedBasisGetCollocatedGrad(basis, impl->colograd1d); CeedChk(ierr); 26184a01de5SJeremy L Thompson ierr = CeedBasisSetData(basis, (void *)&impl); CeedChk(ierr); 262fe2413ffSjeremylt 263*2f86a920SJeremy L Thompson Ceed parent; 264*2f86a920SJeremy L Thompson ierr = CeedGetParent(ceed, &parent); 265*2f86a920SJeremy L Thompson CeedTensorContract contract; 266*2f86a920SJeremy L Thompson ierr = CeedTensorContractCreate(parent, &contract); CeedChk(ierr); 267*2f86a920SJeremy L Thompson ierr = CeedBasisSetTensorContract(basis, &contract); CeedChk(ierr); 268*2f86a920SJeremy L Thompson 269fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Apply", 270fe2413ffSjeremylt CeedBasisApply_Ref); CeedChk(ierr); 271fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Destroy", 27284a01de5SJeremy L Thompson CeedBasisDestroyTensor_Ref); CeedChk(ierr); 27321617c04Sjeremylt return 0; 27421617c04Sjeremylt } 275a8de75f0Sjeremylt 27684a01de5SJeremy L Thompson 27784a01de5SJeremy L Thompson 278667bc5fcSjeremylt int CeedBasisCreateH1_Ref(CeedElemTopology topo, CeedInt dim, 279a8de75f0Sjeremylt CeedInt ndof, CeedInt nqpts, 280a8de75f0Sjeremylt const CeedScalar *interp, 281a8de75f0Sjeremylt const CeedScalar *grad, 282a8de75f0Sjeremylt const CeedScalar *qref, 283a8de75f0Sjeremylt const CeedScalar *qweight, 284a8de75f0Sjeremylt CeedBasis basis) { 285fe2413ffSjeremylt int ierr; 286fe2413ffSjeremylt Ceed ceed; 287fe2413ffSjeremylt ierr = CeedBasisGetCeed(basis, &ceed); CeedChk(ierr); 288fe2413ffSjeremylt 289*2f86a920SJeremy L Thompson CeedTensorContract contract; 290*2f86a920SJeremy L Thompson ierr = CeedTensorContractCreate(ceed, &contract); CeedChk(ierr); 291*2f86a920SJeremy L Thompson ierr = CeedBasisSetTensorContract(basis, &contract); CeedChk(ierr); 292*2f86a920SJeremy L Thompson 293fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Apply", 294fe2413ffSjeremylt CeedBasisApply_Ref); CeedChk(ierr); 295fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Destroy", 29684a01de5SJeremy L Thompson CeedBasisDestroyNonTensor_Ref); CeedChk(ierr); 29784a01de5SJeremy L Thompson 298a8de75f0Sjeremylt return 0; 299a8de75f0Sjeremylt } 300