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 17ec3da8bcSJed Brown #include <ceed/ceed.h> 18ec3da8bcSJed Brown #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 //------------------------------------------------------------------------------ 27d1d35e2fSjeremylt static int CeedBasisApply_Ref(CeedBasis basis, CeedInt num_elem, 28d1d35e2fSjeremylt CeedTransposeMode t_mode, CeedEvalMode eval_mode, 29aedaa0e5Sjeremylt CeedVector U, CeedVector V) { 3021617c04Sjeremylt int ierr; 314ce2993fSjeremylt Ceed ceed; 32e15f9bd0SJeremy L Thompson ierr = CeedBasisGetCeed(basis, &ceed); CeedChkBackend(ierr); 33*50c301a5SRezgar Shakeri CeedInt dim, num_comp, num_nodes, num_qpts, Q_comp; 34e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(basis, &dim); CeedChkBackend(ierr); 35d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis, &num_comp); CeedChkBackend(ierr); 36d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis, &num_nodes); CeedChkBackend(ierr); 37d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis, &num_qpts); CeedChkBackend(ierr); 38*50c301a5SRezgar Shakeri ierr = CeedBasisGetNumQuadratureComponents(basis, &Q_comp); 39*50c301a5SRezgar Shakeri CeedChkBackend(ierr); 402f86a920SJeremy L Thompson CeedTensorContract contract; 41e15f9bd0SJeremy L Thompson ierr = CeedBasisGetTensorContract(basis, &contract); CeedChkBackend(ierr); 42d1d35e2fSjeremylt const CeedInt add = (t_mode == CEED_TRANSPOSE); 43aedaa0e5Sjeremylt const CeedScalar *u; 44aedaa0e5Sjeremylt CeedScalar *v; 45a7b7f929Sjeremylt if (U != CEED_VECTOR_NONE) { 46e15f9bd0SJeremy L Thompson ierr = CeedVectorGetArrayRead(U, CEED_MEM_HOST, &u); CeedChkBackend(ierr); 47d1d35e2fSjeremylt } else if (eval_mode != CEED_EVAL_WEIGHT) { 48c042f62fSJeremy L Thompson // LCOV_EXCL_START 49e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 50aedaa0e5Sjeremylt "An input vector is required for this CeedEvalMode"); 51c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 52aedaa0e5Sjeremylt } 539c774eddSJeremy L Thompson ierr = CeedVectorGetArrayWrite(V, CEED_MEM_HOST, &v); CeedChkBackend(ierr); 5421617c04Sjeremylt 558d94b059Sjeremylt // Clear v if operating in transpose 56d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) { 57d1d35e2fSjeremylt const CeedInt v_size = num_elem*num_comp*num_nodes; 58d1d35e2fSjeremylt for (CeedInt i = 0; i < v_size; i++) 5984a01de5SJeremy L Thompson v[i] = (CeedScalar) 0.0; 6021617c04Sjeremylt } 61d1d35e2fSjeremylt bool tensor_basis; 62d1d35e2fSjeremylt ierr = CeedBasisIsTensor(basis, &tensor_basis); CeedChkBackend(ierr); 6384a01de5SJeremy L Thompson // Tensor basis 64d1d35e2fSjeremylt if (tensor_basis) { 65d1d35e2fSjeremylt CeedInt P_1d, Q_1d; 66d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis, &P_1d); CeedChkBackend(ierr); 67d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints1D(basis, &Q_1d); CeedChkBackend(ierr); 68d1d35e2fSjeremylt switch (eval_mode) { 698d94b059Sjeremylt // Interpolate to/from quadrature points 70a2b73c81Sjeremylt case CEED_EVAL_INTERP: { 71dfe03796SJeremy L Thompson CeedBasis_Ref *impl; 72e15f9bd0SJeremy L Thompson ierr = CeedBasisGetData(basis, &impl); CeedChkBackend(ierr); 738c1105f8SJeremy L Thompson if (impl->has_collo_interp) { 74d1d35e2fSjeremylt memcpy(v, u, num_elem*num_comp*num_nodes*sizeof(u[0])); 75dfe03796SJeremy L Thompson } else { 76d1d35e2fSjeremylt CeedInt P = P_1d, Q = Q_1d; 77d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) { 78d1d35e2fSjeremylt P = Q_1d; Q = P_1d; 7921617c04Sjeremylt } 80d1d35e2fSjeremylt CeedInt pre = num_comp*CeedIntPow(P, dim-1), post = num_elem; 81d1d35e2fSjeremylt CeedScalar tmp[2][num_elem*num_comp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 82d1d35e2fSjeremylt const CeedScalar *interp_1d; 83d1d35e2fSjeremylt ierr = CeedBasisGetInterp1D(basis, &interp_1d); CeedChkBackend(ierr); 8421617c04Sjeremylt for (CeedInt d=0; d<dim; d++) { 852f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 86d1d35e2fSjeremylt interp_1d, t_mode, add&&(d==dim-1), 87dfe03796SJeremy L Thompson d==0?u:tmp[d%2], 88dfe03796SJeremy L Thompson d==dim-1?v:tmp[(d+1)%2]); 89e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 9021617c04Sjeremylt pre /= P; 9121617c04Sjeremylt post *= Q; 9221617c04Sjeremylt } 93dfe03796SJeremy L Thompson } 94a2b73c81Sjeremylt } break; 958d94b059Sjeremylt // Evaluate the gradient to/from quadrature points 96a2b73c81Sjeremylt case CEED_EVAL_GRAD: { 9721617c04Sjeremylt // In CEED_NOTRANSPOSE mode: 98d1d35e2fSjeremylt // u has shape [dim, num_comp, P^dim, num_elem], row-major layout 99d1d35e2fSjeremylt // v has shape [dim, num_comp, Q^dim, num_elem], row-major layout 10021617c04Sjeremylt // In CEED_TRANSPOSE mode, the sizes of u and v are switched. 101d1d35e2fSjeremylt CeedInt P = P_1d, Q = Q_1d; 102d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) { 103d1d35e2fSjeremylt P = Q_1d, Q = Q_1d; 10421617c04Sjeremylt } 10584a01de5SJeremy L Thompson CeedBasis_Ref *impl; 106e15f9bd0SJeremy L Thompson ierr = CeedBasisGetData(basis, &impl); CeedChkBackend(ierr); 107d1d35e2fSjeremylt CeedInt pre = num_comp*CeedIntPow(P, dim-1), post = num_elem; 108d1d35e2fSjeremylt const CeedScalar *interp_1d; 109d1d35e2fSjeremylt ierr = CeedBasisGetInterp1D(basis, &interp_1d); CeedChkBackend(ierr); 1108c1105f8SJeremy L Thompson if (impl->collo_grad_1d) { 111d1d35e2fSjeremylt CeedScalar tmp[2][num_elem*num_comp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 112d1d35e2fSjeremylt CeedScalar interp[num_elem*num_comp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 11384a01de5SJeremy L Thompson // Interpolate to quadrature points (NoTranspose) 11484a01de5SJeremy L Thompson // or Grad to quadrature points (Transpose) 11521617c04Sjeremylt for (CeedInt d=0; d<dim; d++) { 1162f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 117d1d35e2fSjeremylt (t_mode == CEED_NOTRANSPOSE 118d1d35e2fSjeremylt ? interp_1d 1198c1105f8SJeremy L Thompson : impl->collo_grad_1d), 120d1d35e2fSjeremylt t_mode, add&&(d>0), 121d1d35e2fSjeremylt (t_mode == CEED_NOTRANSPOSE 12284a01de5SJeremy L Thompson ? (d==0?u:tmp[d%2]) 123d1d35e2fSjeremylt : u + d*num_qpts*num_comp*num_elem), 124d1d35e2fSjeremylt (t_mode == CEED_NOTRANSPOSE 12584a01de5SJeremy L Thompson ? (d==dim-1?interp:tmp[(d+1)%2]) 12684a01de5SJeremy L Thompson : interp)); 127e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 12821617c04Sjeremylt pre /= P; 12921617c04Sjeremylt post *= Q; 13021617c04Sjeremylt } 13184a01de5SJeremy L Thompson // Grad to quadrature points (NoTranspose) 1328795c945Sjeremylt // or Interpolate to nodes (Transpose) 133d1d35e2fSjeremylt P = Q_1d, Q = Q_1d; 134d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) { 135d1d35e2fSjeremylt P = Q_1d, Q = P_1d; 13684a01de5SJeremy L Thompson } 137d1d35e2fSjeremylt pre = num_comp*CeedIntPow(P, dim-1), post = num_elem; 13884a01de5SJeremy L Thompson for (CeedInt d=0; d<dim; d++) { 1392f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 140d1d35e2fSjeremylt (t_mode == CEED_NOTRANSPOSE 1418c1105f8SJeremy L Thompson ? impl->collo_grad_1d 142d1d35e2fSjeremylt : interp_1d), 143d1d35e2fSjeremylt t_mode, add&&(d==dim-1), 144d1d35e2fSjeremylt (t_mode == CEED_NOTRANSPOSE 14584a01de5SJeremy L Thompson ? interp 14684a01de5SJeremy L Thompson : (d==0?interp:tmp[d%2])), 147d1d35e2fSjeremylt (t_mode == CEED_NOTRANSPOSE 148d1d35e2fSjeremylt ? v + d*num_qpts*num_comp*num_elem 14984a01de5SJeremy L Thompson : (d==dim-1?v:tmp[(d+1)%2]))); 150e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 15184a01de5SJeremy L Thompson pre /= P; 15284a01de5SJeremy L Thompson post *= Q; 15321617c04Sjeremylt } 1548c1105f8SJeremy L Thompson } else if (impl->has_collo_interp) { // Qpts collocated with nodes 155d1d35e2fSjeremylt const CeedScalar *grad_1d; 156d1d35e2fSjeremylt ierr = CeedBasisGetGrad1D(basis, &grad_1d); CeedChkBackend(ierr); 157dfe03796SJeremy L Thompson 158dfe03796SJeremy L Thompson // Dim contractions, identity in other directions 159d1d35e2fSjeremylt CeedInt pre = num_comp*CeedIntPow(P, dim-1), post = num_elem; 160c6158135Sjeremylt for (CeedInt d=0; d<dim; d++) { 161dfe03796SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 162d1d35e2fSjeremylt grad_1d, t_mode, add&&(d>0), 163d1d35e2fSjeremylt t_mode == CEED_NOTRANSPOSE 164d1d35e2fSjeremylt ? u : u+d*num_comp*num_qpts*num_elem, 165d1d35e2fSjeremylt t_mode == CEED_TRANSPOSE 166d1d35e2fSjeremylt ? v : v+d*num_comp*num_qpts*num_elem); 167e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 168c6158135Sjeremylt pre /= P; 169c6158135Sjeremylt post *= Q; 170dfe03796SJeremy L Thompson } 171a7bd39daSjeremylt } else { // Underintegration, P > Q 172d1d35e2fSjeremylt const CeedScalar *grad_1d; 173d1d35e2fSjeremylt ierr = CeedBasisGetGrad1D(basis, &grad_1d); CeedChkBackend(ierr); 174a7bd39daSjeremylt 175d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) { 176d1d35e2fSjeremylt P = Q_1d, Q = P_1d; 177a7bd39daSjeremylt } 178d1d35e2fSjeremylt CeedScalar tmp[2][num_elem*num_comp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 179a7bd39daSjeremylt 180a7bd39daSjeremylt // Dim**2 contractions, apply grad when pass == dim 181a7bd39daSjeremylt for (CeedInt p=0; p<dim; p++) { 182d1d35e2fSjeremylt CeedInt pre = num_comp*CeedIntPow(P, dim-1), post = num_elem; 183a7bd39daSjeremylt for (CeedInt d=0; d<dim; d++) { 184a7bd39daSjeremylt ierr = CeedTensorContractApply(contract, pre, P, post, Q, 185d1d35e2fSjeremylt (p==d)? grad_1d : interp_1d, 186d1d35e2fSjeremylt t_mode, add&&(d==dim-1), 187a7bd39daSjeremylt (d == 0 188d1d35e2fSjeremylt ? (t_mode == CEED_NOTRANSPOSE 189d1d35e2fSjeremylt ? u : u+p*num_comp*num_qpts*num_elem) 190a7bd39daSjeremylt : tmp[d%2]), 191a7bd39daSjeremylt (d == dim-1 192d1d35e2fSjeremylt ? (t_mode == CEED_TRANSPOSE 193d1d35e2fSjeremylt ? v : v+p*num_comp*num_qpts*num_elem) 194a7bd39daSjeremylt : tmp[(d+1)%2])); 195e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 196a7bd39daSjeremylt pre /= P; 197a7bd39daSjeremylt post *= Q; 198a7bd39daSjeremylt } 199a7bd39daSjeremylt } 200a7bd39daSjeremylt } 201a2b73c81Sjeremylt } break; 2028d94b059Sjeremylt // Retrieve interpolation weights 203a2b73c81Sjeremylt case CEED_EVAL_WEIGHT: { 204d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) 205c042f62fSJeremy L Thompson // LCOV_EXCL_START 206e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 20721617c04Sjeremylt "CEED_EVAL_WEIGHT incompatible with CEED_TRANSPOSE"); 208c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 209d1d35e2fSjeremylt CeedInt Q = Q_1d; 210d1d35e2fSjeremylt const CeedScalar *q_weight_1d; 211d1d35e2fSjeremylt ierr = CeedBasisGetQWeights(basis, &q_weight_1d); CeedChkBackend(ierr); 21221617c04Sjeremylt for (CeedInt d=0; d<dim; d++) { 213b5cf12eeSjeremylt CeedInt pre = CeedIntPow(Q, dim-d-1), post = CeedIntPow(Q, d); 214a2b73c81Sjeremylt for (CeedInt i=0; i<pre; i++) 215a2b73c81Sjeremylt for (CeedInt j=0; j<Q; j++) 21684a01de5SJeremy L Thompson for (CeedInt k=0; k<post; k++) { 217d1d35e2fSjeremylt CeedScalar w = q_weight_1d[j] 218d1d35e2fSjeremylt * (d == 0 ? 1 : v[((i*Q + j)*post + k)*num_elem]); 219d1d35e2fSjeremylt for (CeedInt e=0; e<num_elem; e++) 220d1d35e2fSjeremylt v[((i*Q + j)*post + k)*num_elem + e] = w; 22184a01de5SJeremy L Thompson } 22221617c04Sjeremylt } 223a2b73c81Sjeremylt } break; 224c042f62fSJeremy L Thompson // LCOV_EXCL_START 2258d94b059Sjeremylt // Evaluate the divergence to/from the quadrature points 226a2b73c81Sjeremylt case CEED_EVAL_DIV: 227e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "CEED_EVAL_DIV not supported"); 2288d94b059Sjeremylt // Evaluate the curl to/from the quadrature points 229a2b73c81Sjeremylt case CEED_EVAL_CURL: 230e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "CEED_EVAL_CURL not supported"); 2318d94b059Sjeremylt // Take no action, BasisApply should not have been called 232a2b73c81Sjeremylt case CEED_EVAL_NONE: 233e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 2344b8bea3bSJed Brown "CEED_EVAL_NONE does not make sense in this context"); 235c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 23621617c04Sjeremylt } 237a8de75f0Sjeremylt } else { 238a8de75f0Sjeremylt // Non-tensor basis 239d1d35e2fSjeremylt switch (eval_mode) { 24084a01de5SJeremy L Thompson // Interpolate to/from quadrature points 241a8de75f0Sjeremylt case CEED_EVAL_INTERP: { 242*50c301a5SRezgar Shakeri CeedInt P = num_nodes, Q = Q_comp*num_qpts; 2436c58de82SJeremy L Thompson const CeedScalar *interp; 244e15f9bd0SJeremy L Thompson ierr = CeedBasisGetInterp(basis, &interp); CeedChkBackend(ierr); 245d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) { 246*50c301a5SRezgar Shakeri P = Q_comp*num_qpts; Q = num_nodes; 247a8de75f0Sjeremylt } 248d1d35e2fSjeremylt ierr = CeedTensorContractApply(contract, num_comp, P, num_elem, Q, 249d1d35e2fSjeremylt interp, t_mode, add, u, v); 250e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 251a8de75f0Sjeremylt } 252a8de75f0Sjeremylt break; 25384a01de5SJeremy L Thompson // Evaluate the gradient to/from quadrature points 254a8de75f0Sjeremylt case CEED_EVAL_GRAD: { 255d1d35e2fSjeremylt CeedInt P = num_nodes, Q = num_qpts; 256d1d35e2fSjeremylt CeedInt dim_stride = num_qpts * num_comp * num_elem; 257d1d35e2fSjeremylt CeedInt grad_stride = num_qpts * num_nodes; 2586c58de82SJeremy L Thompson const CeedScalar *grad; 259e15f9bd0SJeremy L Thompson ierr = CeedBasisGetGrad(basis, &grad); CeedChkBackend(ierr); 260d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) { 261d1d35e2fSjeremylt P = num_qpts; Q = num_nodes; 262475a782bSnbeams for (CeedInt d = 0; d < dim; d++) { 263d1d35e2fSjeremylt ierr = CeedTensorContractApply(contract, num_comp, P, num_elem, Q, 264d1d35e2fSjeremylt grad + d * grad_stride, t_mode, add, 265d1d35e2fSjeremylt u + d * dim_stride, v); CeedChkBackend(ierr); 266475a782bSnbeams } 267475a782bSnbeams } else { 268475a782bSnbeams for (CeedInt d = 0; d < dim; d++) { 269d1d35e2fSjeremylt ierr = CeedTensorContractApply(contract, num_comp, P, num_elem, Q, 270d1d35e2fSjeremylt grad + d * grad_stride, t_mode, add, 271d1d35e2fSjeremylt u, v + d * dim_stride); CeedChkBackend(ierr); 272475a782bSnbeams } 273475a782bSnbeams } 274a8de75f0Sjeremylt } 275a8de75f0Sjeremylt break; 27684a01de5SJeremy L Thompson // Retrieve interpolation weights 277a8de75f0Sjeremylt case CEED_EVAL_WEIGHT: { 278d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) 279c042f62fSJeremy L Thompson // LCOV_EXCL_START 280e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 281a8de75f0Sjeremylt "CEED_EVAL_WEIGHT incompatible with CEED_TRANSPOSE"); 282c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 283d1d35e2fSjeremylt const CeedScalar *q_weight; 284d1d35e2fSjeremylt ierr = CeedBasisGetQWeights(basis, &q_weight); CeedChkBackend(ierr); 285d1d35e2fSjeremylt for (CeedInt i=0; i<num_qpts; i++) 286d1d35e2fSjeremylt for (CeedInt e=0; e<num_elem; e++) 287d1d35e2fSjeremylt v[i*num_elem + e] = q_weight[i]; 288a8de75f0Sjeremylt } break; 28984a01de5SJeremy L Thompson // Evaluate the divergence to/from the quadrature points 290*50c301a5SRezgar Shakeri case CEED_EVAL_DIV: { 291*50c301a5SRezgar Shakeri CeedInt P = num_nodes, Q = num_qpts; 292*50c301a5SRezgar Shakeri const CeedScalar *div; 293*50c301a5SRezgar Shakeri ierr = CeedBasisGetDiv(basis, &div); CeedChkBackend(ierr); 294*50c301a5SRezgar Shakeri if (t_mode == CEED_TRANSPOSE) { 295*50c301a5SRezgar Shakeri P = num_qpts; Q = num_nodes; 296*50c301a5SRezgar Shakeri } 297*50c301a5SRezgar Shakeri ierr = CeedTensorContractApply(contract, num_comp, P, num_elem, Q, 298*50c301a5SRezgar Shakeri div, t_mode, add, u, v); 299*50c301a5SRezgar Shakeri CeedChkBackend(ierr); 300*50c301a5SRezgar Shakeri } break; 301*50c301a5SRezgar Shakeri // LCOV_EXCL_START 30284a01de5SJeremy L Thompson // Evaluate the curl to/from the quadrature points 303a8de75f0Sjeremylt case CEED_EVAL_CURL: 304e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "CEED_EVAL_CURL not supported"); 30584a01de5SJeremy L Thompson // Take no action, BasisApply should not have been called 306a8de75f0Sjeremylt case CEED_EVAL_NONE: 307e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 308a8de75f0Sjeremylt "CEED_EVAL_NONE does not make sense in this context"); 309c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 310a8de75f0Sjeremylt } 311a8de75f0Sjeremylt } 312a7b7f929Sjeremylt if (U != CEED_VECTOR_NONE) { 313e15f9bd0SJeremy L Thompson ierr = CeedVectorRestoreArrayRead(U, &u); CeedChkBackend(ierr); 314aedaa0e5Sjeremylt } 315e15f9bd0SJeremy L Thompson ierr = CeedVectorRestoreArray(V, &v); CeedChkBackend(ierr); 316e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 31721617c04Sjeremylt } 31821617c04Sjeremylt 319f10650afSjeremylt //------------------------------------------------------------------------------ 320*50c301a5SRezgar Shakeri // Basis Create Non-Tensor H^1 321f10650afSjeremylt //------------------------------------------------------------------------------ 322f10650afSjeremylt int CeedBasisCreateH1_Ref(CeedElemTopology topo, CeedInt dim, 323d1d35e2fSjeremylt CeedInt num_nodes, CeedInt num_qpts, 324f10650afSjeremylt const CeedScalar *interp, 325f10650afSjeremylt const CeedScalar *grad, 326d1d35e2fSjeremylt const CeedScalar *q_ref, 327d1d35e2fSjeremylt const CeedScalar *q_weight, 328f10650afSjeremylt CeedBasis basis) { 329f10650afSjeremylt int ierr; 330f10650afSjeremylt Ceed ceed; 331e15f9bd0SJeremy L Thompson ierr = CeedBasisGetCeed(basis, &ceed); CeedChkBackend(ierr); 332f10650afSjeremylt 333f10650afSjeremylt Ceed parent; 334e15f9bd0SJeremy L Thompson ierr = CeedGetParent(ceed, &parent); CeedChkBackend(ierr); 335f10650afSjeremylt CeedTensorContract contract; 336e15f9bd0SJeremy L Thompson ierr = CeedTensorContractCreate(parent, basis, &contract); CeedChkBackend(ierr); 33734359f16Sjeremylt ierr = CeedBasisSetTensorContract(basis, contract); CeedChkBackend(ierr); 338f10650afSjeremylt 339f10650afSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Apply", 340e15f9bd0SJeremy L Thompson CeedBasisApply_Ref); CeedChkBackend(ierr); 341f10650afSjeremylt 342e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 343f10650afSjeremylt } 344f10650afSjeremylt 345f10650afSjeremylt //------------------------------------------------------------------------------ 346*50c301a5SRezgar Shakeri // Basis Create Non-Tensor H(div) 347*50c301a5SRezgar Shakeri //------------------------------------------------------------------------------ 348*50c301a5SRezgar Shakeri int CeedBasisCreateHdiv_Ref(CeedElemTopology topo, CeedInt dim, 349*50c301a5SRezgar Shakeri CeedInt num_nodes, CeedInt num_qpts, 350*50c301a5SRezgar Shakeri const CeedScalar *interp, 351*50c301a5SRezgar Shakeri const CeedScalar *div, 352*50c301a5SRezgar Shakeri const CeedScalar *q_ref, 353*50c301a5SRezgar Shakeri const CeedScalar *q_weight, 354*50c301a5SRezgar Shakeri CeedBasis basis) { 355*50c301a5SRezgar Shakeri int ierr; 356*50c301a5SRezgar Shakeri Ceed ceed; 357*50c301a5SRezgar Shakeri ierr = CeedBasisGetCeed(basis, &ceed); CeedChkBackend(ierr); 358*50c301a5SRezgar Shakeri 359*50c301a5SRezgar Shakeri Ceed parent; 360*50c301a5SRezgar Shakeri ierr = CeedGetParent(ceed, &parent); CeedChkBackend(ierr); 361*50c301a5SRezgar Shakeri CeedTensorContract contract; 362*50c301a5SRezgar Shakeri ierr = CeedTensorContractCreate(parent, basis, &contract); CeedChkBackend(ierr); 363*50c301a5SRezgar Shakeri ierr = CeedBasisSetTensorContract(basis, contract); CeedChkBackend(ierr); 364*50c301a5SRezgar Shakeri 365*50c301a5SRezgar Shakeri ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Apply", 366*50c301a5SRezgar Shakeri CeedBasisApply_Ref); CeedChkBackend(ierr); 367*50c301a5SRezgar Shakeri 368*50c301a5SRezgar Shakeri return CEED_ERROR_SUCCESS; 369*50c301a5SRezgar Shakeri } 370*50c301a5SRezgar Shakeri 371*50c301a5SRezgar Shakeri //------------------------------------------------------------------------------ 372f10650afSjeremylt // Basis Destroy Tensor 373f10650afSjeremylt //------------------------------------------------------------------------------ 37484a01de5SJeremy L Thompson static int CeedBasisDestroyTensor_Ref(CeedBasis basis) { 37584a01de5SJeremy L Thompson int ierr; 3762f86a920SJeremy L Thompson 37784a01de5SJeremy L Thompson CeedBasis_Ref *impl; 378e15f9bd0SJeremy L Thompson ierr = CeedBasisGetData(basis, &impl); CeedChkBackend(ierr); 3798c1105f8SJeremy L Thompson ierr = CeedFree(&impl->collo_grad_1d); CeedChkBackend(ierr); 380e15f9bd0SJeremy L Thompson ierr = CeedFree(&impl); CeedChkBackend(ierr); 38184a01de5SJeremy L Thompson 382e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 38321617c04Sjeremylt } 38421617c04Sjeremylt 385f10650afSjeremylt //------------------------------------------------------------------------------ 386f10650afSjeremylt // Basis Create Tensor 387f10650afSjeremylt //------------------------------------------------------------------------------ 388d1d35e2fSjeremylt int CeedBasisCreateTensorH1_Ref(CeedInt dim, CeedInt P_1d, 389d1d35e2fSjeremylt CeedInt Q_1d, const CeedScalar *interp_1d, 390d1d35e2fSjeremylt const CeedScalar *grad_1d, 391d1d35e2fSjeremylt const CeedScalar *q_ref_1d, 392d1d35e2fSjeremylt const CeedScalar *q_weight_1d, 39321617c04Sjeremylt CeedBasis basis) { 394fe2413ffSjeremylt int ierr; 395fe2413ffSjeremylt Ceed ceed; 396e15f9bd0SJeremy L Thompson ierr = CeedBasisGetCeed(basis, &ceed); CeedChkBackend(ierr); 39784a01de5SJeremy L Thompson CeedBasis_Ref *impl; 398e15f9bd0SJeremy L Thompson ierr = CeedCalloc(1, &impl); CeedChkBackend(ierr); 399dfe03796SJeremy L Thompson // Check for collocated interp 400d1d35e2fSjeremylt if (Q_1d == P_1d) { 401dfe03796SJeremy L Thompson bool collocated = 1; 402d1d35e2fSjeremylt for (CeedInt i=0; i<P_1d; i++) { 403d1d35e2fSjeremylt collocated = collocated && (fabs(interp_1d[i+P_1d*i] - 1.0) < 1e-14); 404d1d35e2fSjeremylt for (CeedInt j=0; j<P_1d; j++) 405dfe03796SJeremy L Thompson if (j != i) 406d1d35e2fSjeremylt collocated = collocated && (fabs(interp_1d[j+P_1d*i]) < 1e-14); 407dfe03796SJeremy L Thompson } 4088c1105f8SJeremy L Thompson impl->has_collo_interp = collocated; 409dfe03796SJeremy L Thompson } 410dfe03796SJeremy L Thompson // Calculate collocated grad 4118c1105f8SJeremy L Thompson if (Q_1d >= P_1d && !impl->has_collo_interp) { 4128c1105f8SJeremy L Thompson ierr = CeedMalloc(Q_1d*Q_1d, &impl->collo_grad_1d); CeedChkBackend(ierr); 4138c1105f8SJeremy L Thompson ierr = CeedBasisGetCollocatedGrad(basis, impl->collo_grad_1d); 414e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 415a7bd39daSjeremylt } 416e15f9bd0SJeremy L Thompson ierr = CeedBasisSetData(basis, impl); CeedChkBackend(ierr); 417fe2413ffSjeremylt 4182f86a920SJeremy L Thompson Ceed parent; 419e15f9bd0SJeremy L Thompson ierr = CeedGetParent(ceed, &parent); CeedChkBackend(ierr); 4202f86a920SJeremy L Thompson CeedTensorContract contract; 421e15f9bd0SJeremy L Thompson ierr = CeedTensorContractCreate(parent, basis, &contract); CeedChkBackend(ierr); 42234359f16Sjeremylt ierr = CeedBasisSetTensorContract(basis, contract); CeedChkBackend(ierr); 4232f86a920SJeremy L Thompson 424fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Apply", 425e15f9bd0SJeremy L Thompson CeedBasisApply_Ref); CeedChkBackend(ierr); 426fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Destroy", 427e15f9bd0SJeremy L Thompson CeedBasisDestroyTensor_Ref); CeedChkBackend(ierr); 428e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 42921617c04Sjeremylt } 430a8de75f0Sjeremylt 431f10650afSjeremylt //------------------------------------------------------------------------------ 432