13d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 321617c04Sjeremylt // 43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 521617c04Sjeremylt // 63d8e8822SJeremy L Thompson // This file is part of CEED: http://github.com/ceed 721617c04Sjeremylt 849aac155SJeremy L Thompson #include <ceed.h> 9ec3da8bcSJed Brown #include <ceed/backend.h> 103d576824SJeremy L Thompson #include <math.h> 113d576824SJeremy L Thompson #include <stdbool.h> 123d576824SJeremy L Thompson #include <string.h> 132b730f8bSJeremy L Thompson 1421617c04Sjeremylt #include "ceed-ref.h" 1521617c04Sjeremylt 16f10650afSjeremylt //------------------------------------------------------------------------------ 17f10650afSjeremylt // Basis Apply 18f10650afSjeremylt //------------------------------------------------------------------------------ 192b730f8bSJeremy L Thompson static int CeedBasisApply_Ref(CeedBasis basis, CeedInt num_elem, CeedTransposeMode t_mode, CeedEvalMode eval_mode, CeedVector U, CeedVector V) { 204ce2993fSjeremylt Ceed ceed; 212b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetCeed(basis, &ceed)); 22c4e3f59bSSebastian Grimberg CeedInt dim, num_comp, q_comp, num_nodes, num_qpts; 232b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetDimension(basis, &dim)); 242b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetNumComponents(basis, &num_comp)); 25c4e3f59bSSebastian Grimberg CeedCallBackend(CeedBasisGetNumQuadratureComponents(basis, eval_mode, &q_comp)); 262b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetNumNodes(basis, &num_nodes)); 272b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetNumQuadraturePoints(basis, &num_qpts)); 282f86a920SJeremy L Thompson CeedTensorContract contract; 292b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetTensorContract(basis, &contract)); 30d1d35e2fSjeremylt const CeedInt add = (t_mode == CEED_TRANSPOSE); 31aedaa0e5Sjeremylt const CeedScalar *u; 32aedaa0e5Sjeremylt CeedScalar *v; 336574a04fSJeremy L Thompson if (U != CEED_VECTOR_NONE) CeedCallBackend(CeedVectorGetArrayRead(U, CEED_MEM_HOST, &u)); 346574a04fSJeremy L Thompson else CeedCheck(eval_mode == CEED_EVAL_WEIGHT, ceed, CEED_ERROR_BACKEND, "An input vector is required for this CeedEvalMode"); 352b730f8bSJeremy L Thompson CeedCallBackend(CeedVectorGetArrayWrite(V, CEED_MEM_HOST, &v)); 3621617c04Sjeremylt 378d94b059Sjeremylt // Clear v if operating in transpose 38d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) { 39d1d35e2fSjeremylt const CeedInt v_size = num_elem * num_comp * num_nodes; 402b730f8bSJeremy L Thompson for (CeedInt i = 0; i < v_size; i++) v[i] = (CeedScalar)0.0; 4121617c04Sjeremylt } 426402da51SJeremy L Thompson bool is_tensor_basis; 436402da51SJeremy L Thompson CeedCallBackend(CeedBasisIsTensor(basis, &is_tensor_basis)); 446402da51SJeremy L Thompson if (is_tensor_basis) { 45c4e3f59bSSebastian Grimberg // Tensor basis 46d1d35e2fSjeremylt CeedInt P_1d, Q_1d; 472b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetNumNodes1D(basis, &P_1d)); 482b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetNumQuadraturePoints1D(basis, &Q_1d)); 49d1d35e2fSjeremylt switch (eval_mode) { 508d94b059Sjeremylt // Interpolate to/from quadrature points 51a2b73c81Sjeremylt case CEED_EVAL_INTERP: { 52dfe03796SJeremy L Thompson CeedBasis_Ref *impl; 532b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetData(basis, &impl)); 548c1105f8SJeremy L Thompson if (impl->has_collo_interp) { 55d1d35e2fSjeremylt memcpy(v, u, num_elem * num_comp * num_nodes * sizeof(u[0])); 56dfe03796SJeremy L Thompson } else { 57d1d35e2fSjeremylt CeedInt P = P_1d, Q = Q_1d; 58d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) { 592b730f8bSJeremy L Thompson P = Q_1d; 602b730f8bSJeremy L Thompson Q = P_1d; 6121617c04Sjeremylt } 62d1d35e2fSjeremylt CeedInt pre = num_comp * CeedIntPow(P, dim - 1), post = num_elem; 63d1d35e2fSjeremylt CeedScalar tmp[2][num_elem * num_comp * Q * CeedIntPow(P > Q ? P : Q, dim - 1)]; 64d1d35e2fSjeremylt const CeedScalar *interp_1d; 652b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetInterp1D(basis, &interp_1d)); 6621617c04Sjeremylt for (CeedInt d = 0; d < dim; d++) { 672b730f8bSJeremy L Thompson CeedCallBackend(CeedTensorContractApply(contract, pre, P, post, Q, interp_1d, t_mode, add && (d == dim - 1), d == 0 ? u : tmp[d % 2], 682b730f8bSJeremy L Thompson d == dim - 1 ? v : tmp[(d + 1) % 2])); 6921617c04Sjeremylt pre /= P; 7021617c04Sjeremylt post *= Q; 7121617c04Sjeremylt } 72dfe03796SJeremy L Thompson } 73a2b73c81Sjeremylt } break; 748d94b059Sjeremylt // Evaluate the gradient to/from quadrature points 75a2b73c81Sjeremylt case CEED_EVAL_GRAD: { 7621617c04Sjeremylt // In CEED_NOTRANSPOSE mode: 77d1d35e2fSjeremylt // u has shape [dim, num_comp, P^dim, num_elem], row-major layout 78d1d35e2fSjeremylt // v has shape [dim, num_comp, Q^dim, num_elem], row-major layout 7921617c04Sjeremylt // In CEED_TRANSPOSE mode, the sizes of u and v are switched. 80d1d35e2fSjeremylt CeedInt P = P_1d, Q = Q_1d; 81d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) { 82d1d35e2fSjeremylt P = Q_1d, Q = Q_1d; 8321617c04Sjeremylt } 8484a01de5SJeremy L Thompson CeedBasis_Ref *impl; 852b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetData(basis, &impl)); 86d1d35e2fSjeremylt CeedInt pre = num_comp * CeedIntPow(P, dim - 1), post = num_elem; 87d1d35e2fSjeremylt const CeedScalar *interp_1d; 882b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetInterp1D(basis, &interp_1d)); 898c1105f8SJeremy L Thompson if (impl->collo_grad_1d) { 90d1d35e2fSjeremylt CeedScalar tmp[2][num_elem * num_comp * Q * CeedIntPow(P > Q ? P : Q, dim - 1)]; 91d1d35e2fSjeremylt CeedScalar interp[num_elem * num_comp * Q * CeedIntPow(P > Q ? P : Q, dim - 1)]; 9284a01de5SJeremy L Thompson // Interpolate to quadrature points (NoTranspose) 9384a01de5SJeremy L Thompson // or Grad to quadrature points (Transpose) 9421617c04Sjeremylt for (CeedInt d = 0; d < dim; d++) { 952b730f8bSJeremy L Thompson CeedCallBackend(CeedTensorContractApply(contract, pre, P, post, Q, (t_mode == CEED_NOTRANSPOSE ? interp_1d : impl->collo_grad_1d), t_mode, 962b730f8bSJeremy L Thompson add && (d > 0), 972b730f8bSJeremy L Thompson (t_mode == CEED_NOTRANSPOSE ? (d == 0 ? u : tmp[d % 2]) : u + d * num_qpts * num_comp * num_elem), 982b730f8bSJeremy L Thompson (t_mode == CEED_NOTRANSPOSE ? (d == dim - 1 ? interp : tmp[(d + 1) % 2]) : interp))); 9921617c04Sjeremylt pre /= P; 10021617c04Sjeremylt post *= Q; 10121617c04Sjeremylt } 10284a01de5SJeremy L Thompson // Grad to quadrature points (NoTranspose) 1038795c945Sjeremylt // or Interpolate to nodes (Transpose) 104d1d35e2fSjeremylt P = Q_1d, Q = Q_1d; 105d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) { 106d1d35e2fSjeremylt P = Q_1d, Q = P_1d; 10784a01de5SJeremy L Thompson } 108d1d35e2fSjeremylt pre = num_comp * CeedIntPow(P, dim - 1), post = num_elem; 10984a01de5SJeremy L Thompson for (CeedInt d = 0; d < dim; d++) { 1102b730f8bSJeremy L Thompson CeedCallBackend(CeedTensorContractApply( 1112b730f8bSJeremy L Thompson contract, pre, P, post, Q, (t_mode == CEED_NOTRANSPOSE ? impl->collo_grad_1d : interp_1d), t_mode, add && (d == dim - 1), 1122b730f8bSJeremy L Thompson (t_mode == CEED_NOTRANSPOSE ? interp : (d == 0 ? interp : tmp[d % 2])), 1132b730f8bSJeremy L Thompson (t_mode == CEED_NOTRANSPOSE ? v + d * num_qpts * num_comp * num_elem : (d == dim - 1 ? v : tmp[(d + 1) % 2])))); 11484a01de5SJeremy L Thompson pre /= P; 11584a01de5SJeremy L Thompson post *= Q; 11621617c04Sjeremylt } 1178c1105f8SJeremy L Thompson } else if (impl->has_collo_interp) { // Qpts collocated with nodes 118d1d35e2fSjeremylt const CeedScalar *grad_1d; 1192b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetGrad1D(basis, &grad_1d)); 120dfe03796SJeremy L Thompson 121dfe03796SJeremy L Thompson // Dim contractions, identity in other directions 122d1d35e2fSjeremylt CeedInt pre = num_comp * CeedIntPow(P, dim - 1), post = num_elem; 123c6158135Sjeremylt for (CeedInt d = 0; d < dim; d++) { 1242b730f8bSJeremy L Thompson CeedCallBackend(CeedTensorContractApply(contract, pre, P, post, Q, grad_1d, t_mode, add && (d > 0), 1252b730f8bSJeremy L Thompson t_mode == CEED_NOTRANSPOSE ? u : u + d * num_comp * num_qpts * num_elem, 1262b730f8bSJeremy L Thompson t_mode == CEED_TRANSPOSE ? v : v + d * num_comp * num_qpts * num_elem)); 127c6158135Sjeremylt pre /= P; 128c6158135Sjeremylt post *= Q; 129dfe03796SJeremy L Thompson } 130a7bd39daSjeremylt } else { // Underintegration, P > Q 131d1d35e2fSjeremylt const CeedScalar *grad_1d; 1322b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetGrad1D(basis, &grad_1d)); 133a7bd39daSjeremylt 134d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) { 135d1d35e2fSjeremylt P = Q_1d, Q = P_1d; 136a7bd39daSjeremylt } 137d1d35e2fSjeremylt CeedScalar tmp[2][num_elem * num_comp * Q * CeedIntPow(P > Q ? P : Q, dim - 1)]; 138a7bd39daSjeremylt 139a7bd39daSjeremylt // Dim**2 contractions, apply grad when pass == dim 140a7bd39daSjeremylt for (CeedInt p = 0; p < dim; p++) { 141d1d35e2fSjeremylt CeedInt pre = num_comp * CeedIntPow(P, dim - 1), post = num_elem; 142a7bd39daSjeremylt for (CeedInt d = 0; d < dim; d++) { 1432b730f8bSJeremy L Thompson CeedCallBackend(CeedTensorContractApply( 1442b730f8bSJeremy L Thompson contract, pre, P, post, Q, (p == d) ? grad_1d : interp_1d, t_mode, add && (d == dim - 1), 1452b730f8bSJeremy L Thompson (d == 0 ? (t_mode == CEED_NOTRANSPOSE ? u : u + p * num_comp * num_qpts * num_elem) : tmp[d % 2]), 1462b730f8bSJeremy L Thompson (d == dim - 1 ? (t_mode == CEED_TRANSPOSE ? v : v + p * num_comp * num_qpts * num_elem) : tmp[(d + 1) % 2]))); 147a7bd39daSjeremylt pre /= P; 148a7bd39daSjeremylt post *= Q; 149a7bd39daSjeremylt } 150a7bd39daSjeremylt } 151a7bd39daSjeremylt } 152a2b73c81Sjeremylt } break; 1538d94b059Sjeremylt // Retrieve interpolation weights 154a2b73c81Sjeremylt case CEED_EVAL_WEIGHT: { 1556574a04fSJeremy L Thompson CeedCheck(t_mode == CEED_NOTRANSPOSE, ceed, CEED_ERROR_BACKEND, "CEED_EVAL_WEIGHT incompatible with CEED_TRANSPOSE"); 156d1d35e2fSjeremylt CeedInt Q = Q_1d; 157d1d35e2fSjeremylt const CeedScalar *q_weight_1d; 1582b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetQWeights(basis, &q_weight_1d)); 15921617c04Sjeremylt for (CeedInt d = 0; d < dim; d++) { 160b5cf12eeSjeremylt CeedInt pre = CeedIntPow(Q, dim - d - 1), post = CeedIntPow(Q, d); 1612b730f8bSJeremy L Thompson for (CeedInt i = 0; i < pre; i++) { 1622b730f8bSJeremy L Thompson for (CeedInt j = 0; j < Q; j++) { 16384a01de5SJeremy L Thompson for (CeedInt k = 0; k < post; k++) { 1642b730f8bSJeremy L Thompson CeedScalar w = q_weight_1d[j] * (d == 0 ? 1 : v[((i * Q + j) * post + k) * num_elem]); 1652b730f8bSJeremy L Thompson for (CeedInt e = 0; e < num_elem; e++) v[((i * Q + j) * post + k) * num_elem + e] = w; 1662b730f8bSJeremy L Thompson } 1672b730f8bSJeremy L Thompson } 16884a01de5SJeremy L Thompson } 16921617c04Sjeremylt } 170a2b73c81Sjeremylt } break; 171c042f62fSJeremy L Thompson // LCOV_EXCL_START 1728d94b059Sjeremylt // Evaluate the divergence to/from the quadrature points 173a2b73c81Sjeremylt case CEED_EVAL_DIV: 174e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "CEED_EVAL_DIV not supported"); 1758d94b059Sjeremylt // Evaluate the curl to/from the quadrature points 176a2b73c81Sjeremylt case CEED_EVAL_CURL: 177e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "CEED_EVAL_CURL not supported"); 1788d94b059Sjeremylt // Take no action, BasisApply should not have been called 179a2b73c81Sjeremylt case CEED_EVAL_NONE: 1802b730f8bSJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "CEED_EVAL_NONE does not make sense in this context"); 181c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 18221617c04Sjeremylt } 183a8de75f0Sjeremylt } else { 184a8de75f0Sjeremylt // Non-tensor basis 185c4e3f59bSSebastian Grimberg CeedInt P = num_nodes, Q = num_qpts; 186d1d35e2fSjeremylt switch (eval_mode) { 18784a01de5SJeremy L Thompson // Interpolate to/from quadrature points 188a8de75f0Sjeremylt case CEED_EVAL_INTERP: { 1896c58de82SJeremy L Thompson const CeedScalar *interp; 1902b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetInterp(basis, &interp)); 191c4e3f59bSSebastian Grimberg CeedCallBackend(CeedTensorContractStridedApply(contract, num_comp, P, num_elem, q_comp, Q, interp, t_mode, add, u, v)); 1922b730f8bSJeremy L Thompson } break; 19384a01de5SJeremy L Thompson // Evaluate the gradient to/from quadrature points 194a8de75f0Sjeremylt case CEED_EVAL_GRAD: { 1956c58de82SJeremy L Thompson const CeedScalar *grad; 1962b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetGrad(basis, &grad)); 197c4e3f59bSSebastian Grimberg CeedCallBackend(CeedTensorContractStridedApply(contract, num_comp, P, num_elem, q_comp, Q, grad, t_mode, add, u, v)); 198c4e3f59bSSebastian Grimberg } break; 199c4e3f59bSSebastian Grimberg // Evaluate the divergence to/from the quadrature points 200c4e3f59bSSebastian Grimberg case CEED_EVAL_DIV: { 201c4e3f59bSSebastian Grimberg const CeedScalar *div; 202c4e3f59bSSebastian Grimberg CeedCallBackend(CeedBasisGetDiv(basis, &div)); 203c4e3f59bSSebastian Grimberg CeedCallBackend(CeedTensorContractStridedApply(contract, num_comp, P, num_elem, q_comp, Q, div, t_mode, add, u, v)); 204c4e3f59bSSebastian Grimberg } break; 205c4e3f59bSSebastian Grimberg // Evaluate the curl to/from the quadrature points 206c4e3f59bSSebastian Grimberg case CEED_EVAL_CURL: { 207c4e3f59bSSebastian Grimberg const CeedScalar *curl; 208c4e3f59bSSebastian Grimberg CeedCallBackend(CeedBasisGetCurl(basis, &curl)); 209c4e3f59bSSebastian Grimberg CeedCallBackend(CeedTensorContractStridedApply(contract, num_comp, P, num_elem, q_comp, Q, curl, t_mode, add, u, v)); 2102b730f8bSJeremy L Thompson } break; 21184a01de5SJeremy L Thompson // Retrieve interpolation weights 212a8de75f0Sjeremylt case CEED_EVAL_WEIGHT: { 2136574a04fSJeremy L Thompson CeedCheck(t_mode == CEED_NOTRANSPOSE, ceed, CEED_ERROR_BACKEND, "CEED_EVAL_WEIGHT incompatible with CEED_TRANSPOSE"); 214d1d35e2fSjeremylt const CeedScalar *q_weight; 2152b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetQWeights(basis, &q_weight)); 2162b730f8bSJeremy L Thompson for (CeedInt i = 0; i < num_qpts; i++) { 2172b730f8bSJeremy L Thompson for (CeedInt e = 0; e < num_elem; e++) v[i * num_elem + e] = q_weight[i]; 2182b730f8bSJeremy L Thompson } 219a8de75f0Sjeremylt } break; 22050c301a5SRezgar Shakeri // LCOV_EXCL_START 22184a01de5SJeremy L Thompson // Take no action, BasisApply should not have been called 222a8de75f0Sjeremylt case CEED_EVAL_NONE: 2232b730f8bSJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "CEED_EVAL_NONE does not make sense in this context"); 224c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 225a8de75f0Sjeremylt } 226a8de75f0Sjeremylt } 227a7b7f929Sjeremylt if (U != CEED_VECTOR_NONE) { 2282b730f8bSJeremy L Thompson CeedCallBackend(CeedVectorRestoreArrayRead(U, &u)); 229aedaa0e5Sjeremylt } 2302b730f8bSJeremy L Thompson CeedCallBackend(CeedVectorRestoreArray(V, &v)); 23102f1ab5cSSebastian Grimberg 232e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 23321617c04Sjeremylt } 23421617c04Sjeremylt 235f10650afSjeremylt //------------------------------------------------------------------------------ 236*b2165e7aSSebastian Grimberg // Basis Destroy Tensor 237*b2165e7aSSebastian Grimberg //------------------------------------------------------------------------------ 238*b2165e7aSSebastian Grimberg static int CeedBasisDestroyTensor_Ref(CeedBasis basis) { 239*b2165e7aSSebastian Grimberg CeedBasis_Ref *impl; 240*b2165e7aSSebastian Grimberg CeedCallBackend(CeedBasisGetData(basis, &impl)); 241*b2165e7aSSebastian Grimberg CeedCallBackend(CeedFree(&impl->collo_grad_1d)); 242*b2165e7aSSebastian Grimberg CeedCallBackend(CeedFree(&impl)); 243*b2165e7aSSebastian Grimberg 244*b2165e7aSSebastian Grimberg return CEED_ERROR_SUCCESS; 245*b2165e7aSSebastian Grimberg } 246*b2165e7aSSebastian Grimberg 247*b2165e7aSSebastian Grimberg //------------------------------------------------------------------------------ 248*b2165e7aSSebastian Grimberg // Basis Create Tensor 249*b2165e7aSSebastian Grimberg //------------------------------------------------------------------------------ 250*b2165e7aSSebastian Grimberg int CeedBasisCreateTensorH1_Ref(CeedInt dim, CeedInt P_1d, CeedInt Q_1d, const CeedScalar *interp_1d, const CeedScalar *grad_1d, 251*b2165e7aSSebastian Grimberg const CeedScalar *q_ref_1d, const CeedScalar *q_weight_1d, CeedBasis basis) { 252*b2165e7aSSebastian Grimberg Ceed ceed; 253*b2165e7aSSebastian Grimberg CeedCallBackend(CeedBasisGetCeed(basis, &ceed)); 254*b2165e7aSSebastian Grimberg CeedBasis_Ref *impl; 255*b2165e7aSSebastian Grimberg CeedCallBackend(CeedCalloc(1, &impl)); 256*b2165e7aSSebastian Grimberg // Check for collocated interp 257*b2165e7aSSebastian Grimberg if (Q_1d == P_1d) { 258*b2165e7aSSebastian Grimberg bool collocated = 1; 259*b2165e7aSSebastian Grimberg for (CeedInt i = 0; i < P_1d; i++) { 260*b2165e7aSSebastian Grimberg collocated = collocated && (fabs(interp_1d[i + P_1d * i] - 1.0) < 1e-14); 261*b2165e7aSSebastian Grimberg for (CeedInt j = 0; j < P_1d; j++) { 262*b2165e7aSSebastian Grimberg if (j != i) collocated = collocated && (fabs(interp_1d[j + P_1d * i]) < 1e-14); 263*b2165e7aSSebastian Grimberg } 264*b2165e7aSSebastian Grimberg } 265*b2165e7aSSebastian Grimberg impl->has_collo_interp = collocated; 266*b2165e7aSSebastian Grimberg } 267*b2165e7aSSebastian Grimberg // Calculate collocated grad 268*b2165e7aSSebastian Grimberg if (Q_1d >= P_1d && !impl->has_collo_interp) { 269*b2165e7aSSebastian Grimberg CeedCallBackend(CeedMalloc(Q_1d * Q_1d, &impl->collo_grad_1d)); 270*b2165e7aSSebastian Grimberg CeedCallBackend(CeedBasisGetCollocatedGrad(basis, impl->collo_grad_1d)); 271*b2165e7aSSebastian Grimberg } 272*b2165e7aSSebastian Grimberg CeedCallBackend(CeedBasisSetData(basis, impl)); 273*b2165e7aSSebastian Grimberg 274*b2165e7aSSebastian Grimberg Ceed parent; 275*b2165e7aSSebastian Grimberg CeedCallBackend(CeedGetParent(ceed, &parent)); 276*b2165e7aSSebastian Grimberg CeedTensorContract contract; 277*b2165e7aSSebastian Grimberg CeedCallBackend(CeedTensorContractCreate(parent, basis, &contract)); 278*b2165e7aSSebastian Grimberg CeedCallBackend(CeedBasisSetTensorContract(basis, contract)); 279*b2165e7aSSebastian Grimberg 280*b2165e7aSSebastian Grimberg CeedCallBackend(CeedSetBackendFunction(ceed, "Basis", basis, "Apply", CeedBasisApply_Ref)); 281*b2165e7aSSebastian Grimberg CeedCallBackend(CeedSetBackendFunction(ceed, "Basis", basis, "Destroy", CeedBasisDestroyTensor_Ref)); 282*b2165e7aSSebastian Grimberg 283*b2165e7aSSebastian Grimberg return CEED_ERROR_SUCCESS; 284*b2165e7aSSebastian Grimberg } 285*b2165e7aSSebastian Grimberg 286*b2165e7aSSebastian Grimberg //------------------------------------------------------------------------------ 28750c301a5SRezgar Shakeri // Basis Create Non-Tensor H^1 288f10650afSjeremylt //------------------------------------------------------------------------------ 2892b730f8bSJeremy L Thompson int CeedBasisCreateH1_Ref(CeedElemTopology topo, CeedInt dim, CeedInt num_nodes, CeedInt num_qpts, const CeedScalar *interp, const CeedScalar *grad, 2902b730f8bSJeremy L Thompson const CeedScalar *q_ref, const CeedScalar *q_weight, CeedBasis basis) { 291f10650afSjeremylt Ceed ceed; 2922b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetCeed(basis, &ceed)); 293f10650afSjeremylt 294f10650afSjeremylt Ceed parent; 2952b730f8bSJeremy L Thompson CeedCallBackend(CeedGetParent(ceed, &parent)); 296f10650afSjeremylt CeedTensorContract contract; 2972b730f8bSJeremy L Thompson CeedCallBackend(CeedTensorContractCreate(parent, basis, &contract)); 2982b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisSetTensorContract(basis, contract)); 299f10650afSjeremylt 3002b730f8bSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Basis", basis, "Apply", CeedBasisApply_Ref)); 301f10650afSjeremylt 302e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 303f10650afSjeremylt } 304f10650afSjeremylt 305f10650afSjeremylt //------------------------------------------------------------------------------ 30650c301a5SRezgar Shakeri // Basis Create Non-Tensor H(div) 30750c301a5SRezgar Shakeri //------------------------------------------------------------------------------ 3082b730f8bSJeremy L Thompson int CeedBasisCreateHdiv_Ref(CeedElemTopology topo, CeedInt dim, CeedInt num_nodes, CeedInt num_qpts, const CeedScalar *interp, const CeedScalar *div, 3092b730f8bSJeremy L Thompson const CeedScalar *q_ref, const CeedScalar *q_weight, CeedBasis basis) { 31050c301a5SRezgar Shakeri Ceed ceed; 3112b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetCeed(basis, &ceed)); 31250c301a5SRezgar Shakeri 31350c301a5SRezgar Shakeri Ceed parent; 3142b730f8bSJeremy L Thompson CeedCallBackend(CeedGetParent(ceed, &parent)); 31550c301a5SRezgar Shakeri CeedTensorContract contract; 3162b730f8bSJeremy L Thompson CeedCallBackend(CeedTensorContractCreate(parent, basis, &contract)); 3172b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisSetTensorContract(basis, contract)); 31850c301a5SRezgar Shakeri 3192b730f8bSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Basis", basis, "Apply", CeedBasisApply_Ref)); 32050c301a5SRezgar Shakeri 32150c301a5SRezgar Shakeri return CEED_ERROR_SUCCESS; 32250c301a5SRezgar Shakeri } 32350c301a5SRezgar Shakeri 32450c301a5SRezgar Shakeri //------------------------------------------------------------------------------ 325c4e3f59bSSebastian Grimberg // Basis Create Non-Tensor H(curl) 326c4e3f59bSSebastian Grimberg //------------------------------------------------------------------------------ 327c4e3f59bSSebastian Grimberg int CeedBasisCreateHcurl_Ref(CeedElemTopology topo, CeedInt dim, CeedInt num_nodes, CeedInt num_qpts, const CeedScalar *interp, 328c4e3f59bSSebastian Grimberg const CeedScalar *curl, const CeedScalar *q_ref, const CeedScalar *q_weight, CeedBasis basis) { 329c4e3f59bSSebastian Grimberg Ceed ceed; 330c4e3f59bSSebastian Grimberg CeedCallBackend(CeedBasisGetCeed(basis, &ceed)); 331c4e3f59bSSebastian Grimberg 332c4e3f59bSSebastian Grimberg Ceed parent; 333c4e3f59bSSebastian Grimberg CeedCallBackend(CeedGetParent(ceed, &parent)); 334c4e3f59bSSebastian Grimberg CeedTensorContract contract; 335c4e3f59bSSebastian Grimberg CeedCallBackend(CeedTensorContractCreate(parent, basis, &contract)); 336c4e3f59bSSebastian Grimberg CeedCallBackend(CeedBasisSetTensorContract(basis, contract)); 337c4e3f59bSSebastian Grimberg 338c4e3f59bSSebastian Grimberg CeedCallBackend(CeedSetBackendFunction(ceed, "Basis", basis, "Apply", CeedBasisApply_Ref)); 339c4e3f59bSSebastian Grimberg 340c4e3f59bSSebastian Grimberg return CEED_ERROR_SUCCESS; 341c4e3f59bSSebastian Grimberg } 342c4e3f59bSSebastian Grimberg 343c4e3f59bSSebastian Grimberg //------------------------------------------------------------------------------ 344