1*3d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 2*3d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 321617c04Sjeremylt // 4*3d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 521617c04Sjeremylt // 6*3d8e8822SJeremy L Thompson // This file is part of CEED: http://github.com/ceed 721617c04Sjeremylt 8ec3da8bcSJed Brown #include <ceed/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> 1321617c04Sjeremylt #include "ceed-ref.h" 1421617c04Sjeremylt 15f10650afSjeremylt //------------------------------------------------------------------------------ 16f10650afSjeremylt // Basis Apply 17f10650afSjeremylt //------------------------------------------------------------------------------ 18d1d35e2fSjeremylt static int CeedBasisApply_Ref(CeedBasis basis, CeedInt num_elem, 19d1d35e2fSjeremylt CeedTransposeMode t_mode, CeedEvalMode eval_mode, 20aedaa0e5Sjeremylt CeedVector U, CeedVector V) { 2121617c04Sjeremylt int ierr; 224ce2993fSjeremylt Ceed ceed; 23e15f9bd0SJeremy L Thompson ierr = CeedBasisGetCeed(basis, &ceed); CeedChkBackend(ierr); 2450c301a5SRezgar Shakeri CeedInt dim, num_comp, num_nodes, num_qpts, Q_comp; 25e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(basis, &dim); CeedChkBackend(ierr); 26d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis, &num_comp); CeedChkBackend(ierr); 27d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis, &num_nodes); CeedChkBackend(ierr); 28d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis, &num_qpts); CeedChkBackend(ierr); 2950c301a5SRezgar Shakeri ierr = CeedBasisGetNumQuadratureComponents(basis, &Q_comp); 3050c301a5SRezgar Shakeri CeedChkBackend(ierr); 312f86a920SJeremy L Thompson CeedTensorContract contract; 32e15f9bd0SJeremy L Thompson ierr = CeedBasisGetTensorContract(basis, &contract); CeedChkBackend(ierr); 33d1d35e2fSjeremylt const CeedInt add = (t_mode == CEED_TRANSPOSE); 34aedaa0e5Sjeremylt const CeedScalar *u; 35aedaa0e5Sjeremylt CeedScalar *v; 36a7b7f929Sjeremylt if (U != CEED_VECTOR_NONE) { 37e15f9bd0SJeremy L Thompson ierr = CeedVectorGetArrayRead(U, CEED_MEM_HOST, &u); CeedChkBackend(ierr); 38d1d35e2fSjeremylt } else if (eval_mode != CEED_EVAL_WEIGHT) { 39c042f62fSJeremy L Thompson // LCOV_EXCL_START 40e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 41aedaa0e5Sjeremylt "An input vector is required for this CeedEvalMode"); 42c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 43aedaa0e5Sjeremylt } 449c774eddSJeremy L Thompson ierr = CeedVectorGetArrayWrite(V, CEED_MEM_HOST, &v); CeedChkBackend(ierr); 4521617c04Sjeremylt 468d94b059Sjeremylt // Clear v if operating in transpose 47d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) { 48d1d35e2fSjeremylt const CeedInt v_size = num_elem*num_comp*num_nodes; 49d1d35e2fSjeremylt for (CeedInt i = 0; i < v_size; i++) 5084a01de5SJeremy L Thompson v[i] = (CeedScalar) 0.0; 5121617c04Sjeremylt } 52d1d35e2fSjeremylt bool tensor_basis; 53d1d35e2fSjeremylt ierr = CeedBasisIsTensor(basis, &tensor_basis); CeedChkBackend(ierr); 5484a01de5SJeremy L Thompson // Tensor basis 55d1d35e2fSjeremylt if (tensor_basis) { 56d1d35e2fSjeremylt CeedInt P_1d, Q_1d; 57d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis, &P_1d); CeedChkBackend(ierr); 58d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints1D(basis, &Q_1d); CeedChkBackend(ierr); 59d1d35e2fSjeremylt switch (eval_mode) { 608d94b059Sjeremylt // Interpolate to/from quadrature points 61a2b73c81Sjeremylt case CEED_EVAL_INTERP: { 62dfe03796SJeremy L Thompson CeedBasis_Ref *impl; 63e15f9bd0SJeremy L Thompson ierr = CeedBasisGetData(basis, &impl); CeedChkBackend(ierr); 648c1105f8SJeremy L Thompson if (impl->has_collo_interp) { 65d1d35e2fSjeremylt memcpy(v, u, num_elem*num_comp*num_nodes*sizeof(u[0])); 66dfe03796SJeremy L Thompson } else { 67d1d35e2fSjeremylt CeedInt P = P_1d, Q = Q_1d; 68d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) { 69d1d35e2fSjeremylt P = Q_1d; Q = P_1d; 7021617c04Sjeremylt } 71d1d35e2fSjeremylt CeedInt pre = num_comp*CeedIntPow(P, dim-1), post = num_elem; 72d1d35e2fSjeremylt CeedScalar tmp[2][num_elem*num_comp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 73d1d35e2fSjeremylt const CeedScalar *interp_1d; 74d1d35e2fSjeremylt ierr = CeedBasisGetInterp1D(basis, &interp_1d); CeedChkBackend(ierr); 7521617c04Sjeremylt for (CeedInt d=0; d<dim; d++) { 762f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 77d1d35e2fSjeremylt interp_1d, t_mode, add&&(d==dim-1), 78dfe03796SJeremy L Thompson d==0?u:tmp[d%2], 79dfe03796SJeremy L Thompson d==dim-1?v:tmp[(d+1)%2]); 80e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 8121617c04Sjeremylt pre /= P; 8221617c04Sjeremylt post *= Q; 8321617c04Sjeremylt } 84dfe03796SJeremy L Thompson } 85a2b73c81Sjeremylt } break; 868d94b059Sjeremylt // Evaluate the gradient to/from quadrature points 87a2b73c81Sjeremylt case CEED_EVAL_GRAD: { 8821617c04Sjeremylt // In CEED_NOTRANSPOSE mode: 89d1d35e2fSjeremylt // u has shape [dim, num_comp, P^dim, num_elem], row-major layout 90d1d35e2fSjeremylt // v has shape [dim, num_comp, Q^dim, num_elem], row-major layout 9121617c04Sjeremylt // In CEED_TRANSPOSE mode, the sizes of u and v are switched. 92d1d35e2fSjeremylt CeedInt P = P_1d, Q = Q_1d; 93d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) { 94d1d35e2fSjeremylt P = Q_1d, Q = Q_1d; 9521617c04Sjeremylt } 9684a01de5SJeremy L Thompson CeedBasis_Ref *impl; 97e15f9bd0SJeremy L Thompson ierr = CeedBasisGetData(basis, &impl); CeedChkBackend(ierr); 98d1d35e2fSjeremylt CeedInt pre = num_comp*CeedIntPow(P, dim-1), post = num_elem; 99d1d35e2fSjeremylt const CeedScalar *interp_1d; 100d1d35e2fSjeremylt ierr = CeedBasisGetInterp1D(basis, &interp_1d); CeedChkBackend(ierr); 1018c1105f8SJeremy L Thompson if (impl->collo_grad_1d) { 102d1d35e2fSjeremylt CeedScalar tmp[2][num_elem*num_comp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 103d1d35e2fSjeremylt CeedScalar interp[num_elem*num_comp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 10484a01de5SJeremy L Thompson // Interpolate to quadrature points (NoTranspose) 10584a01de5SJeremy L Thompson // or Grad to quadrature points (Transpose) 10621617c04Sjeremylt for (CeedInt d=0; d<dim; d++) { 1072f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 108d1d35e2fSjeremylt (t_mode == CEED_NOTRANSPOSE 109d1d35e2fSjeremylt ? interp_1d 1108c1105f8SJeremy L Thompson : impl->collo_grad_1d), 111d1d35e2fSjeremylt t_mode, add&&(d>0), 112d1d35e2fSjeremylt (t_mode == CEED_NOTRANSPOSE 11384a01de5SJeremy L Thompson ? (d==0?u:tmp[d%2]) 114d1d35e2fSjeremylt : u + d*num_qpts*num_comp*num_elem), 115d1d35e2fSjeremylt (t_mode == CEED_NOTRANSPOSE 11684a01de5SJeremy L Thompson ? (d==dim-1?interp:tmp[(d+1)%2]) 11784a01de5SJeremy L Thompson : interp)); 118e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 11921617c04Sjeremylt pre /= P; 12021617c04Sjeremylt post *= Q; 12121617c04Sjeremylt } 12284a01de5SJeremy L Thompson // Grad to quadrature points (NoTranspose) 1238795c945Sjeremylt // or Interpolate to nodes (Transpose) 124d1d35e2fSjeremylt P = Q_1d, Q = Q_1d; 125d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) { 126d1d35e2fSjeremylt P = Q_1d, Q = P_1d; 12784a01de5SJeremy L Thompson } 128d1d35e2fSjeremylt pre = num_comp*CeedIntPow(P, dim-1), post = num_elem; 12984a01de5SJeremy L Thompson for (CeedInt d=0; d<dim; d++) { 1302f86a920SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 131d1d35e2fSjeremylt (t_mode == CEED_NOTRANSPOSE 1328c1105f8SJeremy L Thompson ? impl->collo_grad_1d 133d1d35e2fSjeremylt : interp_1d), 134d1d35e2fSjeremylt t_mode, add&&(d==dim-1), 135d1d35e2fSjeremylt (t_mode == CEED_NOTRANSPOSE 13684a01de5SJeremy L Thompson ? interp 13784a01de5SJeremy L Thompson : (d==0?interp:tmp[d%2])), 138d1d35e2fSjeremylt (t_mode == CEED_NOTRANSPOSE 139d1d35e2fSjeremylt ? v + d*num_qpts*num_comp*num_elem 14084a01de5SJeremy L Thompson : (d==dim-1?v:tmp[(d+1)%2]))); 141e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 14284a01de5SJeremy L Thompson pre /= P; 14384a01de5SJeremy L Thompson post *= Q; 14421617c04Sjeremylt } 1458c1105f8SJeremy L Thompson } else if (impl->has_collo_interp) { // Qpts collocated with nodes 146d1d35e2fSjeremylt const CeedScalar *grad_1d; 147d1d35e2fSjeremylt ierr = CeedBasisGetGrad1D(basis, &grad_1d); CeedChkBackend(ierr); 148dfe03796SJeremy L Thompson 149dfe03796SJeremy L Thompson // Dim contractions, identity in other directions 150d1d35e2fSjeremylt CeedInt pre = num_comp*CeedIntPow(P, dim-1), post = num_elem; 151c6158135Sjeremylt for (CeedInt d=0; d<dim; d++) { 152dfe03796SJeremy L Thompson ierr = CeedTensorContractApply(contract, pre, P, post, Q, 153d1d35e2fSjeremylt grad_1d, t_mode, add&&(d>0), 154d1d35e2fSjeremylt t_mode == CEED_NOTRANSPOSE 155d1d35e2fSjeremylt ? u : u+d*num_comp*num_qpts*num_elem, 156d1d35e2fSjeremylt t_mode == CEED_TRANSPOSE 157d1d35e2fSjeremylt ? v : v+d*num_comp*num_qpts*num_elem); 158e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 159c6158135Sjeremylt pre /= P; 160c6158135Sjeremylt post *= Q; 161dfe03796SJeremy L Thompson } 162a7bd39daSjeremylt } else { // Underintegration, P > Q 163d1d35e2fSjeremylt const CeedScalar *grad_1d; 164d1d35e2fSjeremylt ierr = CeedBasisGetGrad1D(basis, &grad_1d); CeedChkBackend(ierr); 165a7bd39daSjeremylt 166d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) { 167d1d35e2fSjeremylt P = Q_1d, Q = P_1d; 168a7bd39daSjeremylt } 169d1d35e2fSjeremylt CeedScalar tmp[2][num_elem*num_comp*Q*CeedIntPow(P>Q?P:Q, dim-1)]; 170a7bd39daSjeremylt 171a7bd39daSjeremylt // Dim**2 contractions, apply grad when pass == dim 172a7bd39daSjeremylt for (CeedInt p=0; p<dim; p++) { 173d1d35e2fSjeremylt CeedInt pre = num_comp*CeedIntPow(P, dim-1), post = num_elem; 174a7bd39daSjeremylt for (CeedInt d=0; d<dim; d++) { 175a7bd39daSjeremylt ierr = CeedTensorContractApply(contract, pre, P, post, Q, 176d1d35e2fSjeremylt (p==d)? grad_1d : interp_1d, 177d1d35e2fSjeremylt t_mode, add&&(d==dim-1), 178a7bd39daSjeremylt (d == 0 179d1d35e2fSjeremylt ? (t_mode == CEED_NOTRANSPOSE 180d1d35e2fSjeremylt ? u : u+p*num_comp*num_qpts*num_elem) 181a7bd39daSjeremylt : tmp[d%2]), 182a7bd39daSjeremylt (d == dim-1 183d1d35e2fSjeremylt ? (t_mode == CEED_TRANSPOSE 184d1d35e2fSjeremylt ? v : v+p*num_comp*num_qpts*num_elem) 185a7bd39daSjeremylt : tmp[(d+1)%2])); 186e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 187a7bd39daSjeremylt pre /= P; 188a7bd39daSjeremylt post *= Q; 189a7bd39daSjeremylt } 190a7bd39daSjeremylt } 191a7bd39daSjeremylt } 192a2b73c81Sjeremylt } break; 1938d94b059Sjeremylt // Retrieve interpolation weights 194a2b73c81Sjeremylt case CEED_EVAL_WEIGHT: { 195d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) 196c042f62fSJeremy L Thompson // LCOV_EXCL_START 197e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 19821617c04Sjeremylt "CEED_EVAL_WEIGHT incompatible with CEED_TRANSPOSE"); 199c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 200d1d35e2fSjeremylt CeedInt Q = Q_1d; 201d1d35e2fSjeremylt const CeedScalar *q_weight_1d; 202d1d35e2fSjeremylt ierr = CeedBasisGetQWeights(basis, &q_weight_1d); CeedChkBackend(ierr); 20321617c04Sjeremylt for (CeedInt d=0; d<dim; d++) { 204b5cf12eeSjeremylt CeedInt pre = CeedIntPow(Q, dim-d-1), post = CeedIntPow(Q, d); 205a2b73c81Sjeremylt for (CeedInt i=0; i<pre; i++) 206a2b73c81Sjeremylt for (CeedInt j=0; j<Q; j++) 20784a01de5SJeremy L Thompson for (CeedInt k=0; k<post; k++) { 208d1d35e2fSjeremylt CeedScalar w = q_weight_1d[j] 209d1d35e2fSjeremylt * (d == 0 ? 1 : v[((i*Q + j)*post + k)*num_elem]); 210d1d35e2fSjeremylt for (CeedInt e=0; e<num_elem; e++) 211d1d35e2fSjeremylt v[((i*Q + j)*post + k)*num_elem + e] = w; 21284a01de5SJeremy L Thompson } 21321617c04Sjeremylt } 214a2b73c81Sjeremylt } break; 215c042f62fSJeremy L Thompson // LCOV_EXCL_START 2168d94b059Sjeremylt // Evaluate the divergence to/from the quadrature points 217a2b73c81Sjeremylt case CEED_EVAL_DIV: 218e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "CEED_EVAL_DIV not supported"); 2198d94b059Sjeremylt // Evaluate the curl to/from the quadrature points 220a2b73c81Sjeremylt case CEED_EVAL_CURL: 221e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "CEED_EVAL_CURL not supported"); 2228d94b059Sjeremylt // Take no action, BasisApply should not have been called 223a2b73c81Sjeremylt case CEED_EVAL_NONE: 224e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 2254b8bea3bSJed Brown "CEED_EVAL_NONE does not make sense in this context"); 226c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 22721617c04Sjeremylt } 228a8de75f0Sjeremylt } else { 229a8de75f0Sjeremylt // Non-tensor basis 230d1d35e2fSjeremylt switch (eval_mode) { 23184a01de5SJeremy L Thompson // Interpolate to/from quadrature points 232a8de75f0Sjeremylt case CEED_EVAL_INTERP: { 23350c301a5SRezgar Shakeri CeedInt P = num_nodes, Q = Q_comp*num_qpts; 2346c58de82SJeremy L Thompson const CeedScalar *interp; 235e15f9bd0SJeremy L Thompson ierr = CeedBasisGetInterp(basis, &interp); CeedChkBackend(ierr); 236d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) { 23750c301a5SRezgar Shakeri P = Q_comp*num_qpts; Q = num_nodes; 238a8de75f0Sjeremylt } 239d1d35e2fSjeremylt ierr = CeedTensorContractApply(contract, num_comp, P, num_elem, Q, 240d1d35e2fSjeremylt interp, t_mode, add, u, v); 241e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 242a8de75f0Sjeremylt } 243a8de75f0Sjeremylt break; 24484a01de5SJeremy L Thompson // Evaluate the gradient to/from quadrature points 245a8de75f0Sjeremylt case CEED_EVAL_GRAD: { 246d1d35e2fSjeremylt CeedInt P = num_nodes, Q = num_qpts; 247d1d35e2fSjeremylt CeedInt dim_stride = num_qpts * num_comp * num_elem; 248d1d35e2fSjeremylt CeedInt grad_stride = num_qpts * num_nodes; 2496c58de82SJeremy L Thompson const CeedScalar *grad; 250e15f9bd0SJeremy L Thompson ierr = CeedBasisGetGrad(basis, &grad); CeedChkBackend(ierr); 251d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) { 252d1d35e2fSjeremylt P = num_qpts; Q = num_nodes; 253475a782bSnbeams for (CeedInt d = 0; d < dim; d++) { 254d1d35e2fSjeremylt ierr = CeedTensorContractApply(contract, num_comp, P, num_elem, Q, 255d1d35e2fSjeremylt grad + d * grad_stride, t_mode, add, 256d1d35e2fSjeremylt u + d * dim_stride, v); CeedChkBackend(ierr); 257475a782bSnbeams } 258475a782bSnbeams } else { 259475a782bSnbeams for (CeedInt d = 0; d < dim; d++) { 260d1d35e2fSjeremylt ierr = CeedTensorContractApply(contract, num_comp, P, num_elem, Q, 261d1d35e2fSjeremylt grad + d * grad_stride, t_mode, add, 262d1d35e2fSjeremylt u, v + d * dim_stride); CeedChkBackend(ierr); 263475a782bSnbeams } 264475a782bSnbeams } 265a8de75f0Sjeremylt } 266a8de75f0Sjeremylt break; 26784a01de5SJeremy L Thompson // Retrieve interpolation weights 268a8de75f0Sjeremylt case CEED_EVAL_WEIGHT: { 269d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) 270c042f62fSJeremy L Thompson // LCOV_EXCL_START 271e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 272a8de75f0Sjeremylt "CEED_EVAL_WEIGHT incompatible with CEED_TRANSPOSE"); 273c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 274d1d35e2fSjeremylt const CeedScalar *q_weight; 275d1d35e2fSjeremylt ierr = CeedBasisGetQWeights(basis, &q_weight); CeedChkBackend(ierr); 276d1d35e2fSjeremylt for (CeedInt i=0; i<num_qpts; i++) 277d1d35e2fSjeremylt for (CeedInt e=0; e<num_elem; e++) 278d1d35e2fSjeremylt v[i*num_elem + e] = q_weight[i]; 279a8de75f0Sjeremylt } break; 28084a01de5SJeremy L Thompson // Evaluate the divergence to/from the quadrature points 28150c301a5SRezgar Shakeri case CEED_EVAL_DIV: { 28250c301a5SRezgar Shakeri CeedInt P = num_nodes, Q = num_qpts; 28350c301a5SRezgar Shakeri const CeedScalar *div; 28450c301a5SRezgar Shakeri ierr = CeedBasisGetDiv(basis, &div); CeedChkBackend(ierr); 28550c301a5SRezgar Shakeri if (t_mode == CEED_TRANSPOSE) { 28650c301a5SRezgar Shakeri P = num_qpts; Q = num_nodes; 28750c301a5SRezgar Shakeri } 28850c301a5SRezgar Shakeri ierr = CeedTensorContractApply(contract, num_comp, P, num_elem, Q, 28950c301a5SRezgar Shakeri div, t_mode, add, u, v); 29050c301a5SRezgar Shakeri CeedChkBackend(ierr); 29150c301a5SRezgar Shakeri } break; 29250c301a5SRezgar Shakeri // LCOV_EXCL_START 29384a01de5SJeremy L Thompson // Evaluate the curl to/from the quadrature points 294a8de75f0Sjeremylt case CEED_EVAL_CURL: 295e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "CEED_EVAL_CURL not supported"); 29684a01de5SJeremy L Thompson // Take no action, BasisApply should not have been called 297a8de75f0Sjeremylt case CEED_EVAL_NONE: 298e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 299a8de75f0Sjeremylt "CEED_EVAL_NONE does not make sense in this context"); 300c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 301a8de75f0Sjeremylt } 302a8de75f0Sjeremylt } 303a7b7f929Sjeremylt if (U != CEED_VECTOR_NONE) { 304e15f9bd0SJeremy L Thompson ierr = CeedVectorRestoreArrayRead(U, &u); CeedChkBackend(ierr); 305aedaa0e5Sjeremylt } 306e15f9bd0SJeremy L Thompson ierr = CeedVectorRestoreArray(V, &v); CeedChkBackend(ierr); 307e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 30821617c04Sjeremylt } 30921617c04Sjeremylt 310f10650afSjeremylt //------------------------------------------------------------------------------ 31150c301a5SRezgar Shakeri // Basis Create Non-Tensor H^1 312f10650afSjeremylt //------------------------------------------------------------------------------ 313f10650afSjeremylt int CeedBasisCreateH1_Ref(CeedElemTopology topo, CeedInt dim, 314d1d35e2fSjeremylt CeedInt num_nodes, CeedInt num_qpts, 315f10650afSjeremylt const CeedScalar *interp, 316f10650afSjeremylt const CeedScalar *grad, 317d1d35e2fSjeremylt const CeedScalar *q_ref, 318d1d35e2fSjeremylt const CeedScalar *q_weight, 319f10650afSjeremylt CeedBasis basis) { 320f10650afSjeremylt int ierr; 321f10650afSjeremylt Ceed ceed; 322e15f9bd0SJeremy L Thompson ierr = CeedBasisGetCeed(basis, &ceed); CeedChkBackend(ierr); 323f10650afSjeremylt 324f10650afSjeremylt Ceed parent; 325e15f9bd0SJeremy L Thompson ierr = CeedGetParent(ceed, &parent); CeedChkBackend(ierr); 326f10650afSjeremylt CeedTensorContract contract; 327e15f9bd0SJeremy L Thompson ierr = CeedTensorContractCreate(parent, basis, &contract); CeedChkBackend(ierr); 32834359f16Sjeremylt ierr = CeedBasisSetTensorContract(basis, contract); CeedChkBackend(ierr); 329f10650afSjeremylt 330f10650afSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Apply", 331e15f9bd0SJeremy L Thompson CeedBasisApply_Ref); CeedChkBackend(ierr); 332f10650afSjeremylt 333e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 334f10650afSjeremylt } 335f10650afSjeremylt 336f10650afSjeremylt //------------------------------------------------------------------------------ 33750c301a5SRezgar Shakeri // Basis Create Non-Tensor H(div) 33850c301a5SRezgar Shakeri //------------------------------------------------------------------------------ 33950c301a5SRezgar Shakeri int CeedBasisCreateHdiv_Ref(CeedElemTopology topo, CeedInt dim, 34050c301a5SRezgar Shakeri CeedInt num_nodes, CeedInt num_qpts, 34150c301a5SRezgar Shakeri const CeedScalar *interp, 34250c301a5SRezgar Shakeri const CeedScalar *div, 34350c301a5SRezgar Shakeri const CeedScalar *q_ref, 34450c301a5SRezgar Shakeri const CeedScalar *q_weight, 34550c301a5SRezgar Shakeri CeedBasis basis) { 34650c301a5SRezgar Shakeri int ierr; 34750c301a5SRezgar Shakeri Ceed ceed; 34850c301a5SRezgar Shakeri ierr = CeedBasisGetCeed(basis, &ceed); CeedChkBackend(ierr); 34950c301a5SRezgar Shakeri 35050c301a5SRezgar Shakeri Ceed parent; 35150c301a5SRezgar Shakeri ierr = CeedGetParent(ceed, &parent); CeedChkBackend(ierr); 35250c301a5SRezgar Shakeri CeedTensorContract contract; 35350c301a5SRezgar Shakeri ierr = CeedTensorContractCreate(parent, basis, &contract); CeedChkBackend(ierr); 35450c301a5SRezgar Shakeri ierr = CeedBasisSetTensorContract(basis, contract); CeedChkBackend(ierr); 35550c301a5SRezgar Shakeri 35650c301a5SRezgar Shakeri ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Apply", 35750c301a5SRezgar Shakeri CeedBasisApply_Ref); CeedChkBackend(ierr); 35850c301a5SRezgar Shakeri 35950c301a5SRezgar Shakeri return CEED_ERROR_SUCCESS; 36050c301a5SRezgar Shakeri } 36150c301a5SRezgar Shakeri 36250c301a5SRezgar Shakeri //------------------------------------------------------------------------------ 363f10650afSjeremylt // Basis Destroy Tensor 364f10650afSjeremylt //------------------------------------------------------------------------------ 36584a01de5SJeremy L Thompson static int CeedBasisDestroyTensor_Ref(CeedBasis basis) { 36684a01de5SJeremy L Thompson int ierr; 3672f86a920SJeremy L Thompson 36884a01de5SJeremy L Thompson CeedBasis_Ref *impl; 369e15f9bd0SJeremy L Thompson ierr = CeedBasisGetData(basis, &impl); CeedChkBackend(ierr); 3708c1105f8SJeremy L Thompson ierr = CeedFree(&impl->collo_grad_1d); CeedChkBackend(ierr); 371e15f9bd0SJeremy L Thompson ierr = CeedFree(&impl); CeedChkBackend(ierr); 37284a01de5SJeremy L Thompson 373e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 37421617c04Sjeremylt } 37521617c04Sjeremylt 376f10650afSjeremylt //------------------------------------------------------------------------------ 377f10650afSjeremylt // Basis Create Tensor 378f10650afSjeremylt //------------------------------------------------------------------------------ 379d1d35e2fSjeremylt int CeedBasisCreateTensorH1_Ref(CeedInt dim, CeedInt P_1d, 380d1d35e2fSjeremylt CeedInt Q_1d, const CeedScalar *interp_1d, 381d1d35e2fSjeremylt const CeedScalar *grad_1d, 382d1d35e2fSjeremylt const CeedScalar *q_ref_1d, 383d1d35e2fSjeremylt const CeedScalar *q_weight_1d, 38421617c04Sjeremylt CeedBasis basis) { 385fe2413ffSjeremylt int ierr; 386fe2413ffSjeremylt Ceed ceed; 387e15f9bd0SJeremy L Thompson ierr = CeedBasisGetCeed(basis, &ceed); CeedChkBackend(ierr); 38884a01de5SJeremy L Thompson CeedBasis_Ref *impl; 389e15f9bd0SJeremy L Thompson ierr = CeedCalloc(1, &impl); CeedChkBackend(ierr); 390dfe03796SJeremy L Thompson // Check for collocated interp 391d1d35e2fSjeremylt if (Q_1d == P_1d) { 392dfe03796SJeremy L Thompson bool collocated = 1; 393d1d35e2fSjeremylt for (CeedInt i=0; i<P_1d; i++) { 394d1d35e2fSjeremylt collocated = collocated && (fabs(interp_1d[i+P_1d*i] - 1.0) < 1e-14); 395d1d35e2fSjeremylt for (CeedInt j=0; j<P_1d; j++) 396dfe03796SJeremy L Thompson if (j != i) 397d1d35e2fSjeremylt collocated = collocated && (fabs(interp_1d[j+P_1d*i]) < 1e-14); 398dfe03796SJeremy L Thompson } 3998c1105f8SJeremy L Thompson impl->has_collo_interp = collocated; 400dfe03796SJeremy L Thompson } 401dfe03796SJeremy L Thompson // Calculate collocated grad 4028c1105f8SJeremy L Thompson if (Q_1d >= P_1d && !impl->has_collo_interp) { 4038c1105f8SJeremy L Thompson ierr = CeedMalloc(Q_1d*Q_1d, &impl->collo_grad_1d); CeedChkBackend(ierr); 4048c1105f8SJeremy L Thompson ierr = CeedBasisGetCollocatedGrad(basis, impl->collo_grad_1d); 405e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 406a7bd39daSjeremylt } 407e15f9bd0SJeremy L Thompson ierr = CeedBasisSetData(basis, impl); CeedChkBackend(ierr); 408fe2413ffSjeremylt 4092f86a920SJeremy L Thompson Ceed parent; 410e15f9bd0SJeremy L Thompson ierr = CeedGetParent(ceed, &parent); CeedChkBackend(ierr); 4112f86a920SJeremy L Thompson CeedTensorContract contract; 412e15f9bd0SJeremy L Thompson ierr = CeedTensorContractCreate(parent, basis, &contract); CeedChkBackend(ierr); 41334359f16Sjeremylt ierr = CeedBasisSetTensorContract(basis, contract); CeedChkBackend(ierr); 4142f86a920SJeremy L Thompson 415fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Apply", 416e15f9bd0SJeremy L Thompson CeedBasisApply_Ref); CeedChkBackend(ierr); 417fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Basis", basis, "Destroy", 418e15f9bd0SJeremy L Thompson CeedBasisDestroyTensor_Ref); CeedChkBackend(ierr); 419e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 42021617c04Sjeremylt } 421a8de75f0Sjeremylt 422f10650afSjeremylt //------------------------------------------------------------------------------ 423