19ba83ac0SJeremy L Thompson // Copyright (c) 2017-2026, 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 //------------------------------------------------------------------------------
CeedBasisApplyCore_Ref(CeedBasis basis,bool apply_add,CeedInt num_elem,CeedTransposeMode t_mode,CeedEvalMode eval_mode,CeedVector U,CeedVector V)19db2becc9SJeremy L Thompson static int CeedBasisApplyCore_Ref(CeedBasis basis, bool apply_add, CeedInt num_elem, CeedTransposeMode t_mode, CeedEvalMode eval_mode, CeedVector U,
20db2becc9SJeremy L Thompson CeedVector V) {
21db2becc9SJeremy L Thompson bool is_tensor_basis, add = apply_add || (t_mode == CEED_TRANSPOSE);
22c4e3f59bSSebastian Grimberg CeedInt dim, num_comp, q_comp, num_nodes, num_qpts;
23ad70ee2cSJeremy L Thompson const CeedScalar *u;
24ad70ee2cSJeremy L Thompson CeedScalar *v;
25ad70ee2cSJeremy L Thompson CeedTensorContract contract;
26ad70ee2cSJeremy L Thompson CeedBasis_Ref *impl;
27ad70ee2cSJeremy L Thompson
28ad70ee2cSJeremy L Thompson CeedCallBackend(CeedBasisGetData(basis, &impl));
292b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetDimension(basis, &dim));
302b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetNumComponents(basis, &num_comp));
31c4e3f59bSSebastian Grimberg CeedCallBackend(CeedBasisGetNumQuadratureComponents(basis, eval_mode, &q_comp));
322b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetNumNodes(basis, &num_nodes));
332b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetNumQuadraturePoints(basis, &num_qpts));
342b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetTensorContract(basis, &contract));
356574a04fSJeremy L Thompson if (U != CEED_VECTOR_NONE) CeedCallBackend(CeedVectorGetArrayRead(U, CEED_MEM_HOST, &u));
369bc66399SJeremy L Thompson else CeedCheck(eval_mode == CEED_EVAL_WEIGHT, CeedBasisReturnCeed(basis), CEED_ERROR_BACKEND, "An input vector is required for this CeedEvalMode");
378d94b059Sjeremylt // Clear v if operating in transpose
38db2becc9SJeremy L Thompson if (apply_add) CeedCallBackend(CeedVectorGetArray(V, CEED_MEM_HOST, &v));
39db2becc9SJeremy L Thompson else CeedCallBackend(CeedVectorGetArrayWrite(V, CEED_MEM_HOST, &v));
40ad70ee2cSJeremy L Thompson
41db2becc9SJeremy L Thompson if (t_mode == CEED_TRANSPOSE && !apply_add) {
42db2becc9SJeremy L Thompson CeedSize len;
43db2becc9SJeremy L Thompson
44db2becc9SJeremy L Thompson CeedCallBackend(CeedVectorGetLength(V, &len));
45db2becc9SJeremy L Thompson for (CeedInt i = 0; i < len; i++) v[i] = 0.0;
4621617c04Sjeremylt }
47ad70ee2cSJeremy L Thompson
486402da51SJeremy L Thompson CeedCallBackend(CeedBasisIsTensor(basis, &is_tensor_basis));
496402da51SJeremy L Thompson if (is_tensor_basis) {
50c4e3f59bSSebastian Grimberg // Tensor basis
51d1d35e2fSjeremylt CeedInt P_1d, Q_1d;
52ad70ee2cSJeremy L Thompson
532b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetNumNodes1D(basis, &P_1d));
542b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetNumQuadraturePoints1D(basis, &Q_1d));
55d1d35e2fSjeremylt switch (eval_mode) {
568d94b059Sjeremylt // Interpolate to/from quadrature points
57a2b73c81Sjeremylt case CEED_EVAL_INTERP: {
58aa4b4a9fSJeremy L Thompson if (impl->is_collocated) {
59d1d35e2fSjeremylt memcpy(v, u, num_elem * num_comp * num_nodes * sizeof(u[0]));
60dfe03796SJeremy L Thompson } else {
61d1d35e2fSjeremylt CeedInt P = P_1d, Q = Q_1d;
62ad70ee2cSJeremy L Thompson
63d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) {
642b730f8bSJeremy L Thompson P = Q_1d;
652b730f8bSJeremy L Thompson Q = P_1d;
6621617c04Sjeremylt }
67d1d35e2fSjeremylt CeedInt pre = num_comp * CeedIntPow(P, dim - 1), post = num_elem;
68d1d35e2fSjeremylt CeedScalar tmp[2][num_elem * num_comp * Q * CeedIntPow(P > Q ? P : Q, dim - 1)];
69d1d35e2fSjeremylt const CeedScalar *interp_1d;
70ad70ee2cSJeremy L Thompson
712b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetInterp1D(basis, &interp_1d));
7221617c04Sjeremylt for (CeedInt d = 0; d < dim; d++) {
732b730f8bSJeremy L Thompson CeedCallBackend(CeedTensorContractApply(contract, pre, P, post, Q, interp_1d, t_mode, add && (d == dim - 1), d == 0 ? u : tmp[d % 2],
742b730f8bSJeremy L Thompson d == dim - 1 ? v : tmp[(d + 1) % 2]));
7521617c04Sjeremylt pre /= P;
7621617c04Sjeremylt post *= Q;
7721617c04Sjeremylt }
78dfe03796SJeremy L Thompson }
79a2b73c81Sjeremylt } break;
808d94b059Sjeremylt // Evaluate the gradient to/from quadrature points
81a2b73c81Sjeremylt case CEED_EVAL_GRAD: {
8221617c04Sjeremylt // In CEED_NOTRANSPOSE mode:
83d1d35e2fSjeremylt // u has shape [dim, num_comp, P^dim, num_elem], row-major layout
84d1d35e2fSjeremylt // v has shape [dim, num_comp, Q^dim, num_elem], row-major layout
8521617c04Sjeremylt // In CEED_TRANSPOSE mode, the sizes of u and v are switched.
86d1d35e2fSjeremylt CeedInt P = P_1d, Q = Q_1d;
87ad70ee2cSJeremy L Thompson
88d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) {
891c66c397SJeremy L Thompson P = Q_1d;
901c66c397SJeremy L Thompson Q = Q_1d;
9121617c04Sjeremylt }
92d1d35e2fSjeremylt CeedInt pre = num_comp * CeedIntPow(P, dim - 1), post = num_elem;
93d1d35e2fSjeremylt const CeedScalar *interp_1d;
94ad70ee2cSJeremy L Thompson
952b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetInterp1D(basis, &interp_1d));
968c1105f8SJeremy L Thompson if (impl->collo_grad_1d) {
97d1d35e2fSjeremylt CeedScalar tmp[2][num_elem * num_comp * Q * CeedIntPow(P > Q ? P : Q, dim - 1)];
98d1d35e2fSjeremylt CeedScalar interp[num_elem * num_comp * Q * CeedIntPow(P > Q ? P : Q, dim - 1)];
99ad70ee2cSJeremy L Thompson
10084a01de5SJeremy L Thompson // Interpolate to quadrature points (NoTranspose)
10184a01de5SJeremy L Thompson // or Grad to quadrature points (Transpose)
10221617c04Sjeremylt for (CeedInt d = 0; d < dim; d++) {
1032b730f8bSJeremy L Thompson CeedCallBackend(CeedTensorContractApply(contract, pre, P, post, Q, (t_mode == CEED_NOTRANSPOSE ? interp_1d : impl->collo_grad_1d), t_mode,
104db2becc9SJeremy L Thompson (t_mode == CEED_TRANSPOSE) && (d > 0),
105db2becc9SJeremy L Thompson (t_mode == CEED_NOTRANSPOSE ? (d == 0 ? u : tmp[d % 2]) : &u[d * num_qpts * num_comp * num_elem]),
1062b730f8bSJeremy L Thompson (t_mode == CEED_NOTRANSPOSE ? (d == dim - 1 ? interp : tmp[(d + 1) % 2]) : interp)));
10721617c04Sjeremylt pre /= P;
10821617c04Sjeremylt post *= Q;
10921617c04Sjeremylt }
11084a01de5SJeremy L Thompson // Grad to quadrature points (NoTranspose)
1118795c945Sjeremylt // or Interpolate to nodes (Transpose)
112d1d35e2fSjeremylt P = Q_1d, Q = Q_1d;
113d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) {
1141c66c397SJeremy L Thompson P = Q_1d;
1151c66c397SJeremy L Thompson Q = P_1d;
11684a01de5SJeremy L Thompson }
117d1d35e2fSjeremylt pre = num_comp * CeedIntPow(P, dim - 1), post = num_elem;
11884a01de5SJeremy L Thompson for (CeedInt d = 0; d < dim; d++) {
1191a8516d0SJames Wright CeedCallBackend(CeedTensorContractApply(contract, pre, P, post, Q, (t_mode == CEED_NOTRANSPOSE ? impl->collo_grad_1d : interp_1d), t_mode,
120db2becc9SJeremy L Thompson (t_mode == CEED_NOTRANSPOSE && apply_add) || (t_mode == CEED_TRANSPOSE && (d == dim - 1)),
1212b730f8bSJeremy L Thompson (t_mode == CEED_NOTRANSPOSE ? interp : (d == 0 ? interp : tmp[d % 2])),
1221a8516d0SJames Wright (t_mode == CEED_NOTRANSPOSE ? &v[d * num_qpts * num_comp * num_elem]
1231a8516d0SJames Wright : (d == dim - 1 ? v : tmp[(d + 1) % 2]))));
12484a01de5SJeremy L Thompson pre /= P;
12584a01de5SJeremy L Thompson post *= Q;
12621617c04Sjeremylt }
127aa4b4a9fSJeremy L Thompson } else if (impl->is_collocated) { // Qpts collocated with nodes
128d1d35e2fSjeremylt const CeedScalar *grad_1d;
129ad70ee2cSJeremy L Thompson
1302b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetGrad1D(basis, &grad_1d));
131dfe03796SJeremy L Thompson
132dfe03796SJeremy L Thompson // Dim contractions, identity in other directions
133d1d35e2fSjeremylt CeedInt pre = num_comp * CeedIntPow(P, dim - 1), post = num_elem;
134ad70ee2cSJeremy L Thompson
135c6158135Sjeremylt for (CeedInt d = 0; d < dim; d++) {
1362b730f8bSJeremy L Thompson CeedCallBackend(CeedTensorContractApply(contract, pre, P, post, Q, grad_1d, t_mode, add && (d > 0),
137db2becc9SJeremy L Thompson t_mode == CEED_NOTRANSPOSE ? u : &u[d * num_comp * num_qpts * num_elem],
138db2becc9SJeremy L Thompson t_mode == CEED_TRANSPOSE ? v : &v[d * num_comp * num_qpts * num_elem]));
139c6158135Sjeremylt pre /= P;
140c6158135Sjeremylt post *= Q;
141dfe03796SJeremy L Thompson }
142a7bd39daSjeremylt } else { // Underintegration, P > Q
143d1d35e2fSjeremylt const CeedScalar *grad_1d;
144ad70ee2cSJeremy L Thompson
1452b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetGrad1D(basis, &grad_1d));
146a7bd39daSjeremylt
147d1d35e2fSjeremylt if (t_mode == CEED_TRANSPOSE) {
1481c66c397SJeremy L Thompson P = Q_1d;
1491c66c397SJeremy L Thompson Q = P_1d;
150a7bd39daSjeremylt }
151d1d35e2fSjeremylt CeedScalar tmp[2][num_elem * num_comp * Q * CeedIntPow(P > Q ? P : Q, dim - 1)];
152a7bd39daSjeremylt
153a7bd39daSjeremylt // Dim**2 contractions, apply grad when pass == dim
154a7bd39daSjeremylt for (CeedInt p = 0; p < dim; p++) {
155d1d35e2fSjeremylt CeedInt pre = num_comp * CeedIntPow(P, dim - 1), post = num_elem;
156ad70ee2cSJeremy L Thompson
157a7bd39daSjeremylt for (CeedInt d = 0; d < dim; d++) {
1582b730f8bSJeremy L Thompson CeedCallBackend(CeedTensorContractApply(
1592b730f8bSJeremy L Thompson contract, pre, P, post, Q, (p == d) ? grad_1d : interp_1d, t_mode, add && (d == dim - 1),
160db2becc9SJeremy L Thompson (d == 0 ? (t_mode == CEED_NOTRANSPOSE ? u : &u[p * num_comp * num_qpts * num_elem]) : tmp[d % 2]),
161db2becc9SJeremy L Thompson (d == dim - 1 ? (t_mode == CEED_TRANSPOSE ? v : &v[p * num_comp * num_qpts * num_elem]) : tmp[(d + 1) % 2])));
162a7bd39daSjeremylt pre /= P;
163a7bd39daSjeremylt post *= Q;
164a7bd39daSjeremylt }
165a7bd39daSjeremylt }
166a7bd39daSjeremylt }
167a2b73c81Sjeremylt } break;
1688d94b059Sjeremylt // Retrieve interpolation weights
169a2b73c81Sjeremylt case CEED_EVAL_WEIGHT: {
170d1d35e2fSjeremylt CeedInt Q = Q_1d;
171d1d35e2fSjeremylt const CeedScalar *q_weight_1d;
172ad70ee2cSJeremy L Thompson
1739bc66399SJeremy L Thompson CeedCheck(t_mode == CEED_NOTRANSPOSE, CeedBasisReturnCeed(basis), CEED_ERROR_BACKEND, "CEED_EVAL_WEIGHT incompatible with CEED_TRANSPOSE");
1742b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetQWeights(basis, &q_weight_1d));
17521617c04Sjeremylt for (CeedInt d = 0; d < dim; d++) {
176b5cf12eeSjeremylt CeedInt pre = CeedIntPow(Q, dim - d - 1), post = CeedIntPow(Q, d);
177ad70ee2cSJeremy L Thompson
1782b730f8bSJeremy L Thompson for (CeedInt i = 0; i < pre; i++) {
1792b730f8bSJeremy L Thompson for (CeedInt j = 0; j < Q; j++) {
18084a01de5SJeremy L Thompson for (CeedInt k = 0; k < post; k++) {
181ad70ee2cSJeremy L Thompson const CeedScalar w = q_weight_1d[j] * (d == 0 ? 1 : v[((i * Q + j) * post + k) * num_elem]);
182ad70ee2cSJeremy L Thompson
1832b730f8bSJeremy L Thompson for (CeedInt e = 0; e < num_elem; e++) v[((i * Q + j) * post + k) * num_elem + e] = w;
1842b730f8bSJeremy L Thompson }
1852b730f8bSJeremy L Thompson }
18684a01de5SJeremy L Thompson }
18721617c04Sjeremylt }
188a2b73c81Sjeremylt } break;
189c042f62fSJeremy L Thompson // LCOV_EXCL_START
190a2b73c81Sjeremylt case CEED_EVAL_DIV:
191a2b73c81Sjeremylt case CEED_EVAL_CURL:
1929bc66399SJeremy L Thompson return CeedError(CeedBasisReturnCeed(basis), CEED_ERROR_BACKEND, "%s not supported", CeedEvalModes[eval_mode]);
193a2b73c81Sjeremylt case CEED_EVAL_NONE:
1949bc66399SJeremy L Thompson return CeedError(CeedBasisReturnCeed(basis), CEED_ERROR_BACKEND, "CEED_EVAL_NONE does not make sense in this context");
195c042f62fSJeremy L Thompson // LCOV_EXCL_STOP
19621617c04Sjeremylt }
197a8de75f0Sjeremylt } else {
198a8de75f0Sjeremylt // Non-tensor basis
199c4e3f59bSSebastian Grimberg CeedInt P = num_nodes, Q = num_qpts;
200ad70ee2cSJeremy L Thompson
201d1d35e2fSjeremylt switch (eval_mode) {
20284a01de5SJeremy L Thompson // Interpolate to/from quadrature points
203a8de75f0Sjeremylt case CEED_EVAL_INTERP: {
2046c58de82SJeremy L Thompson const CeedScalar *interp;
205ad70ee2cSJeremy L Thompson
2062b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetInterp(basis, &interp));
207c4e3f59bSSebastian Grimberg CeedCallBackend(CeedTensorContractStridedApply(contract, num_comp, P, num_elem, q_comp, Q, interp, t_mode, add, u, v));
2082b730f8bSJeremy L Thompson } break;
20984a01de5SJeremy L Thompson // Evaluate the gradient to/from quadrature points
210a8de75f0Sjeremylt case CEED_EVAL_GRAD: {
2116c58de82SJeremy L Thompson const CeedScalar *grad;
212ad70ee2cSJeremy L Thompson
2132b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetGrad(basis, &grad));
214c4e3f59bSSebastian Grimberg CeedCallBackend(CeedTensorContractStridedApply(contract, num_comp, P, num_elem, q_comp, Q, grad, t_mode, add, u, v));
215c4e3f59bSSebastian Grimberg } break;
216c4e3f59bSSebastian Grimberg // Evaluate the divergence to/from the quadrature points
217c4e3f59bSSebastian Grimberg case CEED_EVAL_DIV: {
218c4e3f59bSSebastian Grimberg const CeedScalar *div;
219ad70ee2cSJeremy L Thompson
220c4e3f59bSSebastian Grimberg CeedCallBackend(CeedBasisGetDiv(basis, &div));
221c4e3f59bSSebastian Grimberg CeedCallBackend(CeedTensorContractStridedApply(contract, num_comp, P, num_elem, q_comp, Q, div, t_mode, add, u, v));
222c4e3f59bSSebastian Grimberg } break;
223c4e3f59bSSebastian Grimberg // Evaluate the curl to/from the quadrature points
224c4e3f59bSSebastian Grimberg case CEED_EVAL_CURL: {
225c4e3f59bSSebastian Grimberg const CeedScalar *curl;
226ad70ee2cSJeremy L Thompson
227c4e3f59bSSebastian Grimberg CeedCallBackend(CeedBasisGetCurl(basis, &curl));
228c4e3f59bSSebastian Grimberg CeedCallBackend(CeedTensorContractStridedApply(contract, num_comp, P, num_elem, q_comp, Q, curl, t_mode, add, u, v));
2292b730f8bSJeremy L Thompson } break;
23084a01de5SJeremy L Thompson // Retrieve interpolation weights
231a8de75f0Sjeremylt case CEED_EVAL_WEIGHT: {
232d1d35e2fSjeremylt const CeedScalar *q_weight;
233ad70ee2cSJeremy L Thompson
2349bc66399SJeremy L Thompson CeedCheck(t_mode == CEED_NOTRANSPOSE, CeedBasisReturnCeed(basis), CEED_ERROR_BACKEND, "CEED_EVAL_WEIGHT incompatible with CEED_TRANSPOSE");
2352b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisGetQWeights(basis, &q_weight));
2362b730f8bSJeremy L Thompson for (CeedInt i = 0; i < num_qpts; i++) {
2372b730f8bSJeremy L Thompson for (CeedInt e = 0; e < num_elem; e++) v[i * num_elem + e] = q_weight[i];
2382b730f8bSJeremy L Thompson }
239a8de75f0Sjeremylt } break;
24050c301a5SRezgar Shakeri // LCOV_EXCL_START
241a8de75f0Sjeremylt case CEED_EVAL_NONE:
2429bc66399SJeremy L Thompson return CeedError(CeedBasisReturnCeed(basis), CEED_ERROR_BACKEND, "CEED_EVAL_NONE does not make sense in this context");
243c042f62fSJeremy L Thompson // LCOV_EXCL_STOP
244a8de75f0Sjeremylt }
245a8de75f0Sjeremylt }
246a7b7f929Sjeremylt if (U != CEED_VECTOR_NONE) {
2472b730f8bSJeremy L Thompson CeedCallBackend(CeedVectorRestoreArrayRead(U, &u));
248aedaa0e5Sjeremylt }
2492b730f8bSJeremy L Thompson CeedCallBackend(CeedVectorRestoreArray(V, &v));
250e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS;
25121617c04Sjeremylt }
25221617c04Sjeremylt
CeedBasisApply_Ref(CeedBasis basis,CeedInt num_elem,CeedTransposeMode t_mode,CeedEvalMode eval_mode,CeedVector U,CeedVector V)253db2becc9SJeremy L Thompson static int CeedBasisApply_Ref(CeedBasis basis, CeedInt num_elem, CeedTransposeMode t_mode, CeedEvalMode eval_mode, CeedVector U, CeedVector V) {
254db2becc9SJeremy L Thompson CeedCallBackend(CeedBasisApplyCore_Ref(basis, false, num_elem, t_mode, eval_mode, U, V));
255db2becc9SJeremy L Thompson return CEED_ERROR_SUCCESS;
256db2becc9SJeremy L Thompson }
257db2becc9SJeremy L Thompson
CeedBasisApplyAdd_Ref(CeedBasis basis,CeedInt num_elem,CeedTransposeMode t_mode,CeedEvalMode eval_mode,CeedVector U,CeedVector V)258db2becc9SJeremy L Thompson static int CeedBasisApplyAdd_Ref(CeedBasis basis, CeedInt num_elem, CeedTransposeMode t_mode, CeedEvalMode eval_mode, CeedVector U, CeedVector V) {
259db2becc9SJeremy L Thompson CeedCallBackend(CeedBasisApplyCore_Ref(basis, true, num_elem, t_mode, eval_mode, U, V));
260db2becc9SJeremy L Thompson return CEED_ERROR_SUCCESS;
261db2becc9SJeremy L Thompson }
262db2becc9SJeremy L Thompson
263f10650afSjeremylt //------------------------------------------------------------------------------
264b2165e7aSSebastian Grimberg // Basis Destroy Tensor
265b2165e7aSSebastian Grimberg //------------------------------------------------------------------------------
CeedBasisDestroyTensor_Ref(CeedBasis basis)266b2165e7aSSebastian Grimberg static int CeedBasisDestroyTensor_Ref(CeedBasis basis) {
267b2165e7aSSebastian Grimberg CeedBasis_Ref *impl;
268ad70ee2cSJeremy L Thompson
269b2165e7aSSebastian Grimberg CeedCallBackend(CeedBasisGetData(basis, &impl));
270b2165e7aSSebastian Grimberg CeedCallBackend(CeedFree(&impl->collo_grad_1d));
271b2165e7aSSebastian Grimberg CeedCallBackend(CeedFree(&impl));
272b2165e7aSSebastian Grimberg return CEED_ERROR_SUCCESS;
273b2165e7aSSebastian Grimberg }
274b2165e7aSSebastian Grimberg
275b2165e7aSSebastian Grimberg //------------------------------------------------------------------------------
276b2165e7aSSebastian Grimberg // Basis Create Tensor
277b2165e7aSSebastian Grimberg //------------------------------------------------------------------------------
CeedBasisCreateTensorH1_Ref(CeedInt dim,CeedInt P_1d,CeedInt Q_1d,const CeedScalar * interp_1d,const CeedScalar * grad_1d,const CeedScalar * q_ref_1d,const CeedScalar * q_weight_1d,CeedBasis basis)278b2165e7aSSebastian Grimberg int CeedBasisCreateTensorH1_Ref(CeedInt dim, CeedInt P_1d, CeedInt Q_1d, const CeedScalar *interp_1d, const CeedScalar *grad_1d,
279b2165e7aSSebastian Grimberg const CeedScalar *q_ref_1d, const CeedScalar *q_weight_1d, CeedBasis basis) {
280ca735530SJeremy L Thompson Ceed ceed, ceed_parent;
281b2165e7aSSebastian Grimberg CeedBasis_Ref *impl;
282ad70ee2cSJeremy L Thompson CeedTensorContract contract;
283ad70ee2cSJeremy L Thompson
284ad70ee2cSJeremy L Thompson CeedCallBackend(CeedBasisGetCeed(basis, &ceed));
285ca735530SJeremy L Thompson CeedCallBackend(CeedGetParent(ceed, &ceed_parent));
286ad70ee2cSJeremy L Thompson
287b2165e7aSSebastian Grimberg CeedCallBackend(CeedCalloc(1, &impl));
288b2165e7aSSebastian Grimberg // Calculate collocated grad
289aa4b4a9fSJeremy L Thompson CeedCallBackend(CeedBasisIsCollocated(basis, &impl->is_collocated));
290aa4b4a9fSJeremy L Thompson if (Q_1d >= P_1d && !impl->is_collocated) {
291b2165e7aSSebastian Grimberg CeedCallBackend(CeedMalloc(Q_1d * Q_1d, &impl->collo_grad_1d));
292b2165e7aSSebastian Grimberg CeedCallBackend(CeedBasisGetCollocatedGrad(basis, impl->collo_grad_1d));
293b2165e7aSSebastian Grimberg }
294b2165e7aSSebastian Grimberg CeedCallBackend(CeedBasisSetData(basis, impl));
295b2165e7aSSebastian Grimberg
296a71faab1SSebastian Grimberg CeedCallBackend(CeedTensorContractCreate(ceed_parent, &contract));
297b2165e7aSSebastian Grimberg CeedCallBackend(CeedBasisSetTensorContract(basis, contract));
298*b0f67a9cSJeremy L Thompson CeedCallBackend(CeedTensorContractDestroy(&contract));
299b2165e7aSSebastian Grimberg
300b2165e7aSSebastian Grimberg CeedCallBackend(CeedSetBackendFunction(ceed, "Basis", basis, "Apply", CeedBasisApply_Ref));
301db2becc9SJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Basis", basis, "ApplyAdd", CeedBasisApplyAdd_Ref));
302b2165e7aSSebastian Grimberg CeedCallBackend(CeedSetBackendFunction(ceed, "Basis", basis, "Destroy", CeedBasisDestroyTensor_Ref));
3039bc66399SJeremy L Thompson CeedCallBackend(CeedDestroy(&ceed));
3049bc66399SJeremy L Thompson CeedCallBackend(CeedDestroy(&ceed_parent));
305b2165e7aSSebastian Grimberg return CEED_ERROR_SUCCESS;
306b2165e7aSSebastian Grimberg }
307b2165e7aSSebastian Grimberg
308b2165e7aSSebastian Grimberg //------------------------------------------------------------------------------
30950c301a5SRezgar Shakeri // Basis Create Non-Tensor H^1
310f10650afSjeremylt //------------------------------------------------------------------------------
CeedBasisCreateH1_Ref(CeedElemTopology topo,CeedInt dim,CeedInt num_nodes,CeedInt num_qpts,const CeedScalar * interp,const CeedScalar * grad,const CeedScalar * q_ref,const CeedScalar * q_weight,CeedBasis basis)3112b730f8bSJeremy L Thompson int CeedBasisCreateH1_Ref(CeedElemTopology topo, CeedInt dim, CeedInt num_nodes, CeedInt num_qpts, const CeedScalar *interp, const CeedScalar *grad,
3122b730f8bSJeremy L Thompson const CeedScalar *q_ref, const CeedScalar *q_weight, CeedBasis basis) {
313ca735530SJeremy L Thompson Ceed ceed, ceed_parent;
314f10650afSjeremylt CeedTensorContract contract;
315ad70ee2cSJeremy L Thompson
316ad70ee2cSJeremy L Thompson CeedCallBackend(CeedBasisGetCeed(basis, &ceed));
317ca735530SJeremy L Thompson CeedCallBackend(CeedGetParent(ceed, &ceed_parent));
318ad70ee2cSJeremy L Thompson
319a71faab1SSebastian Grimberg CeedCallBackend(CeedTensorContractCreate(ceed_parent, &contract));
3202b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisSetTensorContract(basis, contract));
321*b0f67a9cSJeremy L Thompson CeedCallBackend(CeedTensorContractDestroy(&contract));
322f10650afSjeremylt
3232b730f8bSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Basis", basis, "Apply", CeedBasisApply_Ref));
324db2becc9SJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Basis", basis, "ApplyAdd", CeedBasisApplyAdd_Ref));
3259bc66399SJeremy L Thompson CeedCallBackend(CeedDestroy(&ceed));
3269bc66399SJeremy L Thompson CeedCallBackend(CeedDestroy(&ceed_parent));
327e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS;
328f10650afSjeremylt }
329f10650afSjeremylt
330f10650afSjeremylt //------------------------------------------------------------------------------
33150c301a5SRezgar Shakeri // Basis Create Non-Tensor H(div)
33250c301a5SRezgar Shakeri //------------------------------------------------------------------------------
CeedBasisCreateHdiv_Ref(CeedElemTopology topo,CeedInt dim,CeedInt num_nodes,CeedInt num_qpts,const CeedScalar * interp,const CeedScalar * div,const CeedScalar * q_ref,const CeedScalar * q_weight,CeedBasis basis)3332b730f8bSJeremy L Thompson int CeedBasisCreateHdiv_Ref(CeedElemTopology topo, CeedInt dim, CeedInt num_nodes, CeedInt num_qpts, const CeedScalar *interp, const CeedScalar *div,
3342b730f8bSJeremy L Thompson const CeedScalar *q_ref, const CeedScalar *q_weight, CeedBasis basis) {
335ca735530SJeremy L Thompson Ceed ceed, ceed_parent;
33650c301a5SRezgar Shakeri CeedTensorContract contract;
337ad70ee2cSJeremy L Thompson
338ad70ee2cSJeremy L Thompson CeedCallBackend(CeedBasisGetCeed(basis, &ceed));
339ca735530SJeremy L Thompson CeedCallBackend(CeedGetParent(ceed, &ceed_parent));
340ad70ee2cSJeremy L Thompson
341a71faab1SSebastian Grimberg CeedCallBackend(CeedTensorContractCreate(ceed_parent, &contract));
3422b730f8bSJeremy L Thompson CeedCallBackend(CeedBasisSetTensorContract(basis, contract));
343*b0f67a9cSJeremy L Thompson CeedCallBackend(CeedTensorContractDestroy(&contract));
34450c301a5SRezgar Shakeri
3452b730f8bSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Basis", basis, "Apply", CeedBasisApply_Ref));
346db2becc9SJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Basis", basis, "ApplyAdd", CeedBasisApplyAdd_Ref));
3479bc66399SJeremy L Thompson CeedCallBackend(CeedDestroy(&ceed));
3489bc66399SJeremy L Thompson CeedCallBackend(CeedDestroy(&ceed_parent));
34950c301a5SRezgar Shakeri return CEED_ERROR_SUCCESS;
35050c301a5SRezgar Shakeri }
35150c301a5SRezgar Shakeri
35250c301a5SRezgar Shakeri //------------------------------------------------------------------------------
353c4e3f59bSSebastian Grimberg // Basis Create Non-Tensor H(curl)
354c4e3f59bSSebastian Grimberg //------------------------------------------------------------------------------
CeedBasisCreateHcurl_Ref(CeedElemTopology topo,CeedInt dim,CeedInt num_nodes,CeedInt num_qpts,const CeedScalar * interp,const CeedScalar * curl,const CeedScalar * q_ref,const CeedScalar * q_weight,CeedBasis basis)355c4e3f59bSSebastian Grimberg int CeedBasisCreateHcurl_Ref(CeedElemTopology topo, CeedInt dim, CeedInt num_nodes, CeedInt num_qpts, const CeedScalar *interp,
356c4e3f59bSSebastian Grimberg const CeedScalar *curl, const CeedScalar *q_ref, const CeedScalar *q_weight, CeedBasis basis) {
357ca735530SJeremy L Thompson Ceed ceed, ceed_parent;
358c4e3f59bSSebastian Grimberg CeedTensorContract contract;
359ad70ee2cSJeremy L Thompson
360ad70ee2cSJeremy L Thompson CeedCallBackend(CeedBasisGetCeed(basis, &ceed));
361ca735530SJeremy L Thompson CeedCallBackend(CeedGetParent(ceed, &ceed_parent));
362ad70ee2cSJeremy L Thompson
363a71faab1SSebastian Grimberg CeedCallBackend(CeedTensorContractCreate(ceed_parent, &contract));
364c4e3f59bSSebastian Grimberg CeedCallBackend(CeedBasisSetTensorContract(basis, contract));
365*b0f67a9cSJeremy L Thompson CeedCallBackend(CeedTensorContractDestroy(&contract));
366c4e3f59bSSebastian Grimberg
367c4e3f59bSSebastian Grimberg CeedCallBackend(CeedSetBackendFunction(ceed, "Basis", basis, "Apply", CeedBasisApply_Ref));
368db2becc9SJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Basis", basis, "ApplyAdd", CeedBasisApplyAdd_Ref));
3699bc66399SJeremy L Thompson CeedCallBackend(CeedDestroy(&ceed));
3709bc66399SJeremy L Thompson CeedCallBackend(CeedDestroy(&ceed_parent));
371c4e3f59bSSebastian Grimberg return CEED_ERROR_SUCCESS;
372c4e3f59bSSebastian Grimberg }
373c4e3f59bSSebastian Grimberg
374c4e3f59bSSebastian Grimberg //------------------------------------------------------------------------------
375