xref: /libCEED/rust/libceed-sys/c-src/backends/ref/ceed-ref-restriction.c (revision 77d1c127eaba12da4c1761ef74a16ca3fc16e493)
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 <stdbool.h>
113d576824SJeremy L Thompson #include <string.h>
122b730f8bSJeremy L Thompson 
1321617c04Sjeremylt #include "ceed-ref.h"
1421617c04Sjeremylt 
15f10650afSjeremylt //------------------------------------------------------------------------------
16f10650afSjeremylt // Core ElemRestriction Apply Code
17f10650afSjeremylt //------------------------------------------------------------------------------
182b730f8bSJeremy L Thompson static inline int CeedElemRestrictionApply_Ref_Core(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
19*77d1c127SSebastian Grimberg                                                     CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u,
203bdd4e5aSSebastian Grimberg                                                     CeedVector v, CeedRequest *request) {
214ce2993fSjeremylt   CeedElemRestriction_Ref *impl;
222b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(r, &impl));
2321617c04Sjeremylt   const CeedScalar *uu;
2421617c04Sjeremylt   CeedScalar       *vv;
25d1d35e2fSjeremylt   CeedInt           num_elem, elem_size, v_offset;
262b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumElements(r, &num_elem));
272b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetElementSize(r, &elem_size));
28d1d35e2fSjeremylt   v_offset = start * blk_size * elem_size * num_comp;
29*77d1c127SSebastian Grimberg   bool is_oriented, is_curl_oriented;
30*77d1c127SSebastian Grimberg   is_oriented      = (impl->orients != NULL);
31*77d1c127SSebastian Grimberg   is_curl_oriented = (impl->curl_orients != NULL);
3221617c04Sjeremylt 
332b730f8bSJeremy L Thompson   CeedCallBackend(CeedVectorGetArrayRead(u, CEED_MEM_HOST, &uu));
349c774eddSJeremy L Thompson   if (t_mode == CEED_TRANSPOSE) {
359c774eddSJeremy L Thompson     // Sum into for transpose mode, e-vec to l-vec
362b730f8bSJeremy L Thompson     CeedCallBackend(CeedVectorGetArray(v, CEED_MEM_HOST, &vv));
379c774eddSJeremy L Thompson   } else {
389c774eddSJeremy L Thompson     // Overwrite for notranspose mode, l-vec to e-vec
392b730f8bSJeremy L Thompson     CeedCallBackend(CeedVectorGetArrayWrite(v, CEED_MEM_HOST, &vv));
409c774eddSJeremy L Thompson   }
417f90ec76Sjeremylt   // Restriction from L-vector to E-vector
4221617c04Sjeremylt   // Perform: v = r * u
43d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
44d979a051Sjeremylt     // No offsets provided, Identity Restriction
45d979a051Sjeremylt     if (!impl->offsets) {
46d1d35e2fSjeremylt       bool has_backend_strides;
472b730f8bSJeremy L Thompson       CeedCallBackend(CeedElemRestrictionHasBackendStrides(r, &has_backend_strides));
48d1d35e2fSjeremylt       if (has_backend_strides) {
49d1d35e2fSjeremylt         // CPU backend strides are {1, elem_size, elem_size*num_comp}
507f90ec76Sjeremylt         // This if branch is left separate to allow better inlining
512b730f8bSJeremy L Thompson         for (CeedInt e = start * blk_size; e < stop * blk_size; e += blk_size) {
522b730f8bSJeremy L Thompson           CeedPragmaSIMD for (CeedInt k = 0; k < num_comp; k++) {
532b730f8bSJeremy L Thompson             CeedPragmaSIMD for (CeedInt n = 0; n < elem_size; n++) {
542b730f8bSJeremy L Thompson               CeedPragmaSIMD for (CeedInt j = 0; j < blk_size; j++) {
552b730f8bSJeremy L Thompson                 vv[e * elem_size * num_comp + (k * elem_size + n) * blk_size + j - v_offset] =
562b730f8bSJeremy L Thompson                     uu[n + k * elem_size + CeedIntMin(e + j, num_elem - 1) * elem_size * num_comp];
572b730f8bSJeremy L Thompson               }
582b730f8bSJeremy L Thompson             }
592b730f8bSJeremy L Thompson           }
602b730f8bSJeremy L Thompson         }
617f90ec76Sjeremylt       } else {
627f90ec76Sjeremylt         // User provided strides
637f90ec76Sjeremylt         CeedInt strides[3];
642b730f8bSJeremy L Thompson         CeedCallBackend(CeedElemRestrictionGetStrides(r, &strides));
652b730f8bSJeremy L Thompson         for (CeedInt e = start * blk_size; e < stop * blk_size; e += blk_size) {
662b730f8bSJeremy L Thompson           CeedPragmaSIMD for (CeedInt k = 0; k < num_comp; k++) {
672b730f8bSJeremy L Thompson             CeedPragmaSIMD for (CeedInt n = 0; n < elem_size; n++) {
682b730f8bSJeremy L Thompson               CeedPragmaSIMD for (CeedInt j = 0; j < blk_size; j++) {
692b730f8bSJeremy L Thompson                 vv[e * elem_size * num_comp + (k * elem_size + n) * blk_size + j - v_offset] =
702b730f8bSJeremy L Thompson                     uu[n * strides[0] + k * strides[1] + CeedIntMin(e + j, num_elem - 1) * strides[2]];
712b730f8bSJeremy L Thompson               }
722b730f8bSJeremy L Thompson             }
732b730f8bSJeremy L Thompson           }
742b730f8bSJeremy L Thompson         }
757509a596Sjeremylt       }
7621617c04Sjeremylt     } else {
77d979a051Sjeremylt       // Offsets provided, standard or blocked restriction
78d1d35e2fSjeremylt       // vv has shape [elem_size, num_comp, num_elem], row-major
79d1d35e2fSjeremylt       // uu has shape [nnodes, num_comp]
802b730f8bSJeremy L Thompson       for (CeedInt e = start * blk_size; e < stop * blk_size; e += blk_size) {
812b730f8bSJeremy L Thompson         CeedPragmaSIMD for (CeedInt k = 0; k < num_comp; k++) {
822b730f8bSJeremy L Thompson           CeedPragmaSIMD for (CeedInt i = 0; i < elem_size * blk_size; i++) {
83*77d1c127SSebastian Grimberg             if (!use_orients || (!is_oriented && !is_curl_oriented)) {
84f30b1135SSebastian Grimberg               // Unsigned restriction
853bdd4e5aSSebastian Grimberg               vv[elem_size * (k * blk_size + num_comp * e) + i - v_offset] = uu[impl->offsets[i + elem_size * e] + k * comp_stride];
86*77d1c127SSebastian Grimberg             } else if (!is_curl_oriented) {
87f30b1135SSebastian Grimberg               // Signed restriction
88f30b1135SSebastian Grimberg               vv[elem_size * (k * blk_size + num_comp * e) + i - v_offset] =
89*77d1c127SSebastian Grimberg                   uu[impl->offsets[i + elem_size * e] + k * comp_stride] * (impl->orients[i + elem_size * e] ? -1.0 : 1.0);
90*77d1c127SSebastian Grimberg             } else {
91*77d1c127SSebastian Grimberg               // Restriction with tridiagonal transformation
92*77d1c127SSebastian Grimberg               CeedInt ii = i % elem_size;
93*77d1c127SSebastian Grimberg               if (ii == 0) {
94*77d1c127SSebastian Grimberg                 vv[elem_size * (k * blk_size + num_comp * e) + i - v_offset] =
95*77d1c127SSebastian Grimberg                     uu[impl->offsets[i + 0 + elem_size * e] + k * comp_stride] * impl->curl_orients[3 * i + 1 + 3 * elem_size * e] +
96*77d1c127SSebastian Grimberg                     uu[impl->offsets[i + 1 + elem_size * e] + k * comp_stride] * impl->curl_orients[3 * i + 2 + 3 * elem_size * e];
97*77d1c127SSebastian Grimberg               } else if (ii == elem_size - 1) {
98*77d1c127SSebastian Grimberg                 vv[elem_size * (k * blk_size + num_comp * e) + i - v_offset] =
99*77d1c127SSebastian Grimberg                     uu[impl->offsets[i - 1 + elem_size * e] + k * comp_stride] * impl->curl_orients[3 * i + 0 + 3 * elem_size * e] +
100*77d1c127SSebastian Grimberg                     uu[impl->offsets[i + 0 + elem_size * e] + k * comp_stride] * impl->curl_orients[3 * i + 1 + 3 * elem_size * e];
101*77d1c127SSebastian Grimberg               } else {
102*77d1c127SSebastian Grimberg                 vv[elem_size * (k * blk_size + num_comp * e) + i - v_offset] =
103*77d1c127SSebastian Grimberg                     uu[impl->offsets[i - 1 + elem_size * e] + k * comp_stride] * impl->curl_orients[3 * i + 0 + 3 * elem_size * e] +
104*77d1c127SSebastian Grimberg                     uu[impl->offsets[i + 0 + elem_size * e] + k * comp_stride] * impl->curl_orients[3 * i + 1 + 3 * elem_size * e] +
105*77d1c127SSebastian Grimberg                     uu[impl->offsets[i + 1 + elem_size * e] + k * comp_stride] * impl->curl_orients[3 * i + 2 + 3 * elem_size * e];
106*77d1c127SSebastian Grimberg               }
107f30b1135SSebastian Grimberg             }
1082b730f8bSJeremy L Thompson           }
1092b730f8bSJeremy L Thompson         }
1102b730f8bSJeremy L Thompson       }
111b435c5a6Srezgarshakeri     }
11221617c04Sjeremylt   } else {
1137f90ec76Sjeremylt     // Restriction from E-vector to L-vector
1148d94b059Sjeremylt     // Performing v += r^T * u
115d979a051Sjeremylt     // No offsets provided, Identity Restriction
116d979a051Sjeremylt     if (!impl->offsets) {
117d1d35e2fSjeremylt       bool has_backend_strides;
1182b730f8bSJeremy L Thompson       CeedCallBackend(CeedElemRestrictionHasBackendStrides(r, &has_backend_strides));
119d1d35e2fSjeremylt       if (has_backend_strides) {
120d1d35e2fSjeremylt         // CPU backend strides are {1, elem_size, elem_size*num_comp}
1217f90ec76Sjeremylt         // This if brach is left separate to allow better inlining
1222b730f8bSJeremy L Thompson         for (CeedInt e = start * blk_size; e < stop * blk_size; e += blk_size) {
1232b730f8bSJeremy L Thompson           CeedPragmaSIMD for (CeedInt k = 0; k < num_comp; k++) {
1242b730f8bSJeremy L Thompson             CeedPragmaSIMD for (CeedInt n = 0; n < elem_size; n++) {
1252b730f8bSJeremy L Thompson               CeedPragmaSIMD for (CeedInt j = 0; j < CeedIntMin(blk_size, num_elem - e); j++) {
1262b730f8bSJeremy L Thompson                 vv[n + k * elem_size + (e + j) * elem_size * num_comp] +=
1272b730f8bSJeremy L Thompson                     uu[e * elem_size * num_comp + (k * elem_size + n) * blk_size + j - v_offset];
1282b730f8bSJeremy L Thompson               }
1292b730f8bSJeremy L Thompson             }
1302b730f8bSJeremy L Thompson           }
1312b730f8bSJeremy L Thompson         }
1327f90ec76Sjeremylt       } else {
1337f90ec76Sjeremylt         // User provided strides
1347f90ec76Sjeremylt         CeedInt strides[3];
1352b730f8bSJeremy L Thompson         CeedCallBackend(CeedElemRestrictionGetStrides(r, &strides));
1362b730f8bSJeremy L Thompson         for (CeedInt e = start * blk_size; e < stop * blk_size; e += blk_size) {
1372b730f8bSJeremy L Thompson           CeedPragmaSIMD for (CeedInt k = 0; k < num_comp; k++) {
1382b730f8bSJeremy L Thompson             CeedPragmaSIMD for (CeedInt n = 0; n < elem_size; n++) {
1392b730f8bSJeremy L Thompson               CeedPragmaSIMD for (CeedInt j = 0; j < CeedIntMin(blk_size, num_elem - e); j++) {
1402b730f8bSJeremy L Thompson                 vv[n * strides[0] + k * strides[1] + (e + j) * strides[2]] +=
1412b730f8bSJeremy L Thompson                     uu[e * elem_size * num_comp + (k * elem_size + n) * blk_size + j - v_offset];
1422b730f8bSJeremy L Thompson               }
1432b730f8bSJeremy L Thompson             }
1442b730f8bSJeremy L Thompson           }
1452b730f8bSJeremy L Thompson         }
146523b8ea0Sjeremylt       }
14721617c04Sjeremylt     } else {
148d979a051Sjeremylt       // Offsets provided, standard or blocked restriction
149d1d35e2fSjeremylt       // uu has shape [elem_size, num_comp, num_elem]
150d1d35e2fSjeremylt       // vv has shape [nnodes, num_comp]
1512b730f8bSJeremy L Thompson       for (CeedInt e = start * blk_size; e < stop * blk_size; e += blk_size) {
1522b730f8bSJeremy L Thompson         for (CeedInt k = 0; k < num_comp; k++) {
1532b730f8bSJeremy L Thompson           for (CeedInt i = 0; i < elem_size * blk_size; i += blk_size) {
1548d94b059Sjeremylt             // Iteration bound set to discard padding elements
1552b730f8bSJeremy L Thompson             for (CeedInt j = i; j < i + CeedIntMin(blk_size, num_elem - e); j++) {
156*77d1c127SSebastian Grimberg               if (!use_orients || (!is_oriented && !is_curl_oriented)) {
157f30b1135SSebastian Grimberg                 // Unsigned restriction
1583bdd4e5aSSebastian Grimberg                 vv[impl->offsets[j + e * elem_size] + k * comp_stride] += uu[elem_size * (k * blk_size + num_comp * e) + j - v_offset];
159*77d1c127SSebastian Grimberg               } else if (!is_curl_oriented) {
160f30b1135SSebastian Grimberg                 // Signed restriction
161f30b1135SSebastian Grimberg                 vv[impl->offsets[j + e * elem_size] + k * comp_stride] +=
162*77d1c127SSebastian Grimberg                     uu[elem_size * (k * blk_size + num_comp * e) + j - v_offset] * (impl->orients[j + e * elem_size] ? -1.0 : 1.0);
163*77d1c127SSebastian Grimberg               } else {
164*77d1c127SSebastian Grimberg                 // Restriction with tridiagonal transformation
165*77d1c127SSebastian Grimberg                 CeedInt jj = j % elem_size;
166*77d1c127SSebastian Grimberg                 if (jj == 0) {
167*77d1c127SSebastian Grimberg                   vv[impl->offsets[j + e * elem_size] + k * comp_stride] +=
168*77d1c127SSebastian Grimberg                       uu[elem_size * (k * blk_size + num_comp * e) + j + 0 - v_offset] * impl->curl_orients[(j + 0) * 3 + 1 + e * 3 * elem_size] +
169*77d1c127SSebastian Grimberg                       uu[elem_size * (k * blk_size + num_comp * e) + j + 1 - v_offset] * impl->curl_orients[(j + 1) * 3 + 0 + e * 3 * elem_size];
170*77d1c127SSebastian Grimberg                 } else if (jj == elem_size - 1) {
171*77d1c127SSebastian Grimberg                   vv[impl->offsets[j + e * elem_size] + k * comp_stride] +=
172*77d1c127SSebastian Grimberg                       uu[elem_size * (k * blk_size + num_comp * e) + j - 1 - v_offset] * impl->curl_orients[(j - 1) * 3 + 2 + e * 3 * elem_size] +
173*77d1c127SSebastian Grimberg                       uu[elem_size * (k * blk_size + num_comp * e) + j + 0 - v_offset] * impl->curl_orients[(j + 0) * 3 + 1 + e * 3 * elem_size];
174*77d1c127SSebastian Grimberg                 } else {
175*77d1c127SSebastian Grimberg                   vv[impl->offsets[j + e * elem_size] + k * comp_stride] +=
176*77d1c127SSebastian Grimberg                       uu[elem_size * (k * blk_size + num_comp * e) + j - 1 - v_offset] * impl->curl_orients[(j - 1) * 3 + 2 + e * 3 * elem_size] +
177*77d1c127SSebastian Grimberg                       uu[elem_size * (k * blk_size + num_comp * e) + j + 0 - v_offset] * impl->curl_orients[(j + 0) * 3 + 1 + e * 3 * elem_size] +
178*77d1c127SSebastian Grimberg                       uu[elem_size * (k * blk_size + num_comp * e) + j + 1 - v_offset] * impl->curl_orients[(j + 1) * 3 + 0 + e * 3 * elem_size];
179*77d1c127SSebastian Grimberg                 }
180f30b1135SSebastian Grimberg               }
18121617c04Sjeremylt             }
182b435c5a6Srezgarshakeri           }
1832b730f8bSJeremy L Thompson         }
1842b730f8bSJeremy L Thompson       }
1852b730f8bSJeremy L Thompson     }
1862b730f8bSJeremy L Thompson   }
1872b730f8bSJeremy L Thompson   CeedCallBackend(CeedVectorRestoreArrayRead(u, &uu));
1882b730f8bSJeremy L Thompson   CeedCallBackend(CeedVectorRestoreArray(v, &vv));
1892b730f8bSJeremy L Thompson   if (request != CEED_REQUEST_IMMEDIATE && request != CEED_REQUEST_ORDERED) *request = NULL;
190e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
19121617c04Sjeremylt }
19221617c04Sjeremylt 
193f10650afSjeremylt //------------------------------------------------------------------------------
194f10650afSjeremylt // ElemRestriction Apply - Common Sizes
195f10650afSjeremylt //------------------------------------------------------------------------------
1962b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_110(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
197*77d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
1983bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
199*77d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 1, 1, comp_stride, start, stop, use_orients, t_mode, u, v, request);
200d979a051Sjeremylt }
201d979a051Sjeremylt 
2022b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_111(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
203*77d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
2043bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
205*77d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 1, 1, 1, start, stop, use_orients, t_mode, u, v, request);
2064d2a38eeSjeremylt }
2074d2a38eeSjeremylt 
2082b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_180(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
209*77d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
2103bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
211*77d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 1, 8, comp_stride, start, stop, use_orients, t_mode, u, v, request);
2129c36149bSjeremylt }
2139c36149bSjeremylt 
2142b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_181(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
215*77d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
2163bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
217*77d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 1, 8, 1, start, stop, use_orients, t_mode, u, v, request);
2189c36149bSjeremylt }
2199c36149bSjeremylt 
2202b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_310(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
221*77d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
2223bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
223*77d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 3, 1, comp_stride, start, stop, use_orients, t_mode, u, v, request);
224d979a051Sjeremylt }
225d979a051Sjeremylt 
2262b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_311(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
227*77d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
2283bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
229*77d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 3, 1, 1, start, stop, use_orients, t_mode, u, v, request);
230d979a051Sjeremylt }
231d979a051Sjeremylt 
2322b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_380(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
233*77d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
2343bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
235*77d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 3, 8, comp_stride, start, stop, use_orients, t_mode, u, v, request);
236d979a051Sjeremylt }
237d979a051Sjeremylt 
2382b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_381(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
239*77d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
2403bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
241*77d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 3, 8, 1, start, stop, use_orients, t_mode, u, v, request);
242d979a051Sjeremylt }
243d979a051Sjeremylt 
244bf4d1581Sjeremylt // LCOV_EXCL_START
2452b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_510(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
246*77d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
2473bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
248*77d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 5, 1, comp_stride, start, stop, use_orients, t_mode, u, v, request);
249d979a051Sjeremylt }
250bf4d1581Sjeremylt // LCOV_EXCL_STOP
251d979a051Sjeremylt 
2522b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_511(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
253*77d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
2543bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
255*77d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 5, 1, 1, start, stop, use_orients, t_mode, u, v, request);
256d979a051Sjeremylt }
257d979a051Sjeremylt 
258bf4d1581Sjeremylt // LCOV_EXCL_START
2592b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_580(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
260*77d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
2613bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
262*77d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 5, 8, comp_stride, start, stop, use_orients, t_mode, u, v, request);
263d979a051Sjeremylt }
264bf4d1581Sjeremylt // LCOV_EXCL_STOP
265d979a051Sjeremylt 
2662b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_581(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
267*77d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
2683bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
269*77d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 5, 8, 1, start, stop, use_orients, t_mode, u, v, request);
2704d2a38eeSjeremylt }
2714d2a38eeSjeremylt 
272f10650afSjeremylt //------------------------------------------------------------------------------
273f10650afSjeremylt // ElemRestriction Apply
274f10650afSjeremylt //------------------------------------------------------------------------------
2752b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref(CeedElemRestriction r, CeedTransposeMode t_mode, CeedVector u, CeedVector v, CeedRequest *request) {
276d1d35e2fSjeremylt   CeedInt num_blk, blk_size, num_comp, comp_stride;
2772b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumBlocks(r, &num_blk));
2782b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetBlockSize(r, &blk_size));
2792b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumComponents(r, &num_comp));
2802b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCompStride(r, &comp_stride));
2817509a596Sjeremylt   CeedElemRestriction_Ref *impl;
2822b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(r, &impl));
2834d2a38eeSjeremylt 
284f30b1135SSebastian Grimberg   return impl->Apply(r, num_comp, blk_size, comp_stride, 0, num_blk, true, t_mode, u, v, request);
285f30b1135SSebastian Grimberg }
286f30b1135SSebastian Grimberg 
287f30b1135SSebastian Grimberg //------------------------------------------------------------------------------
288f30b1135SSebastian Grimberg // ElemRestriction Apply Unsigned
289f30b1135SSebastian Grimberg //------------------------------------------------------------------------------
290f30b1135SSebastian Grimberg static int CeedElemRestrictionApplyUnsigned_Ref(CeedElemRestriction r, CeedTransposeMode t_mode, CeedVector u, CeedVector v, CeedRequest *request) {
291f30b1135SSebastian Grimberg   CeedInt num_blk, blk_size, num_comp, comp_stride;
292f30b1135SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetNumBlocks(r, &num_blk));
293f30b1135SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetBlockSize(r, &blk_size));
294f30b1135SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetNumComponents(r, &num_comp));
295f30b1135SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetCompStride(r, &comp_stride));
296f30b1135SSebastian Grimberg   CeedElemRestriction_Ref *impl;
297f30b1135SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetData(r, &impl));
298f30b1135SSebastian Grimberg 
299f30b1135SSebastian Grimberg   return impl->Apply(r, num_comp, blk_size, comp_stride, 0, num_blk, false, t_mode, u, v, request);
3009c36149bSjeremylt }
301be9261b7Sjeremylt 
302f10650afSjeremylt //------------------------------------------------------------------------------
303f10650afSjeremylt // ElemRestriction Apply Block
304f10650afSjeremylt //------------------------------------------------------------------------------
3052b730f8bSJeremy L Thompson static int CeedElemRestrictionApplyBlock_Ref(CeedElemRestriction r, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
306074cb416Sjeremylt                                              CeedRequest *request) {
307d1d35e2fSjeremylt   CeedInt blk_size, num_comp, comp_stride;
3082b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetBlockSize(r, &blk_size));
3092b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumComponents(r, &num_comp));
3102b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCompStride(r, &comp_stride));
3117509a596Sjeremylt   CeedElemRestriction_Ref *impl;
3122b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(r, &impl));
3134d2a38eeSjeremylt 
314f30b1135SSebastian Grimberg   return impl->Apply(r, num_comp, blk_size, comp_stride, block, block + 1, true, t_mode, u, v, request);
3159c36149bSjeremylt }
316be9261b7Sjeremylt 
317f10650afSjeremylt //------------------------------------------------------------------------------
318bd33150aSjeremylt // ElemRestriction Get Offsets
319bd33150aSjeremylt //------------------------------------------------------------------------------
3202b730f8bSJeremy L Thompson static int CeedElemRestrictionGetOffsets_Ref(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) {
321bd33150aSjeremylt   CeedElemRestriction_Ref *impl;
3222b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
323bd33150aSjeremylt   Ceed ceed;
3242b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCeed(rstr, &ceed));
325bd33150aSjeremylt 
3266574a04fSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only provide to HOST memory");
327bd33150aSjeremylt 
328bd33150aSjeremylt   *offsets = impl->offsets;
329e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
330bd33150aSjeremylt }
331bd33150aSjeremylt 
332bd33150aSjeremylt //------------------------------------------------------------------------------
333*77d1c127SSebastian Grimberg // ElemRestriction Get Orientations
334*77d1c127SSebastian Grimberg //------------------------------------------------------------------------------
335*77d1c127SSebastian Grimberg static int CeedElemRestrictionGetOrientations_Ref(CeedElemRestriction rstr, CeedMemType mem_type, const bool **orients) {
336*77d1c127SSebastian Grimberg   CeedElemRestriction_Ref *impl;
337*77d1c127SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
338*77d1c127SSebastian Grimberg   Ceed ceed;
339*77d1c127SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetCeed(rstr, &ceed));
340*77d1c127SSebastian Grimberg 
341*77d1c127SSebastian Grimberg   if (mem_type != CEED_MEM_HOST) {
342*77d1c127SSebastian Grimberg     // LCOV_EXCL_START
343*77d1c127SSebastian Grimberg     return CeedError(ceed, CEED_ERROR_BACKEND, "Can only provide to HOST memory");
344*77d1c127SSebastian Grimberg     // LCOV_EXCL_STOP
345*77d1c127SSebastian Grimberg   }
346*77d1c127SSebastian Grimberg 
347*77d1c127SSebastian Grimberg   *orients = impl->orients;
348*77d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
349*77d1c127SSebastian Grimberg }
350*77d1c127SSebastian Grimberg 
351*77d1c127SSebastian Grimberg //------------------------------------------------------------------------------
352*77d1c127SSebastian Grimberg // ElemRestriction Get Curl-Conforming Orientations
353*77d1c127SSebastian Grimberg //------------------------------------------------------------------------------
354*77d1c127SSebastian Grimberg static int CeedElemRestrictionGetCurlOrientations_Ref(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **curl_orients) {
355*77d1c127SSebastian Grimberg   CeedElemRestriction_Ref *impl;
356*77d1c127SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
357*77d1c127SSebastian Grimberg   Ceed ceed;
358*77d1c127SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetCeed(rstr, &ceed));
359*77d1c127SSebastian Grimberg 
360*77d1c127SSebastian Grimberg   if (mem_type != CEED_MEM_HOST) {
361*77d1c127SSebastian Grimberg     // LCOV_EXCL_START
362*77d1c127SSebastian Grimberg     return CeedError(ceed, CEED_ERROR_BACKEND, "Can only provide to HOST memory");
363*77d1c127SSebastian Grimberg     // LCOV_EXCL_STOP
364*77d1c127SSebastian Grimberg   }
365*77d1c127SSebastian Grimberg 
366*77d1c127SSebastian Grimberg   *curl_orients = impl->curl_orients;
367*77d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
368*77d1c127SSebastian Grimberg }
369*77d1c127SSebastian Grimberg 
370*77d1c127SSebastian Grimberg //------------------------------------------------------------------------------
371f10650afSjeremylt // ElemRestriction Destroy
372f10650afSjeremylt //------------------------------------------------------------------------------
37321617c04Sjeremylt static int CeedElemRestrictionDestroy_Ref(CeedElemRestriction r) {
374fe2413ffSjeremylt   CeedElemRestriction_Ref *impl;
3752b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(r, &impl));
37621617c04Sjeremylt 
3772b730f8bSJeremy L Thompson   CeedCallBackend(CeedFree(&impl->offsets_allocated));
378*77d1c127SSebastian Grimberg   CeedCallBackend(CeedFree(&impl->orients_allocated));
379*77d1c127SSebastian Grimberg   CeedCallBackend(CeedFree(&impl->curl_orients_allocated));
3802b730f8bSJeremy L Thompson   CeedCallBackend(CeedFree(&impl));
381e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
38221617c04Sjeremylt }
38321617c04Sjeremylt 
384f10650afSjeremylt //------------------------------------------------------------------------------
385f10650afSjeremylt // ElemRestriction Create
386f10650afSjeremylt //------------------------------------------------------------------------------
3872b730f8bSJeremy L Thompson int CeedElemRestrictionCreate_Ref(CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction r) {
38821617c04Sjeremylt   CeedElemRestriction_Ref *impl;
389d1d35e2fSjeremylt   CeedInt                  num_elem, elem_size, num_blk, blk_size, num_comp, comp_stride;
3902b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumElements(r, &num_elem));
3912b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetElementSize(r, &elem_size));
3922b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumBlocks(r, &num_blk));
3932b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetBlockSize(r, &blk_size));
3942b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumComponents(r, &num_comp));
3952b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCompStride(r, &comp_stride));
3964ce2993fSjeremylt   Ceed ceed;
3972b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCeed(r, &ceed));
39821617c04Sjeremylt 
3996574a04fSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Only MemType = HOST supported");
4002b730f8bSJeremy L Thompson   CeedCallBackend(CeedCalloc(1, &impl));
4013661185eSjeremylt 
40292fe105eSJeremy L Thompson   // Offsets data
403d1d35e2fSjeremylt   bool is_strided;
4042b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionIsStrided(r, &is_strided));
405d1d35e2fSjeremylt   if (!is_strided) {
40692fe105eSJeremy L Thompson     // Check indices for ref or memcheck backends
407d1d35e2fSjeremylt     Ceed parent_ceed = ceed, curr_ceed = NULL;
408d1d35e2fSjeremylt     while (parent_ceed != curr_ceed) {
409d1d35e2fSjeremylt       curr_ceed = parent_ceed;
4102b730f8bSJeremy L Thompson       CeedCallBackend(CeedGetParent(curr_ceed, &parent_ceed));
4113661185eSjeremylt     }
4123661185eSjeremylt     const char *resource;
4132b730f8bSJeremy L Thompson     CeedCallBackend(CeedGetResource(parent_ceed, &resource));
4142b730f8bSJeremy L Thompson     if (!strcmp(resource, "/cpu/self/ref/serial") || !strcmp(resource, "/cpu/self/ref/blocked") || !strcmp(resource, "/cpu/self/memcheck/serial") ||
415d1d35e2fSjeremylt         !strcmp(resource, "/cpu/self/memcheck/blocked")) {
416e79b91d9SJeremy L Thompson       CeedSize l_size;
4172b730f8bSJeremy L Thompson       CeedCallBackend(CeedElemRestrictionGetLVectorSize(r, &l_size));
4183661185eSjeremylt 
4192b730f8bSJeremy L Thompson       for (CeedInt i = 0; i < num_elem * elem_size; i++) {
4206574a04fSJeremy L Thompson         CeedCheck(offsets[i] >= 0 && offsets[i] + (num_comp - 1) * comp_stride < l_size, ceed, CEED_ERROR_BACKEND,
4216574a04fSJeremy L Thompson                   "Restriction offset %" CeedInt_FMT " (%" CeedInt_FMT ") out of range [0, %" CeedInt_FMT "]", i, offsets[i], l_size);
4222b730f8bSJeremy L Thompson       }
4232b730f8bSJeremy L Thompson     }
4243661185eSjeremylt 
42592fe105eSJeremy L Thompson     // Copy data
426d1d35e2fSjeremylt     switch (copy_mode) {
42721617c04Sjeremylt       case CEED_COPY_VALUES:
4282b730f8bSJeremy L Thompson         CeedCallBackend(CeedMalloc(num_elem * elem_size, &impl->offsets_allocated));
4292b730f8bSJeremy L Thompson         memcpy(impl->offsets_allocated, offsets, num_elem * elem_size * sizeof(offsets[0]));
430d979a051Sjeremylt         impl->offsets = impl->offsets_allocated;
43121617c04Sjeremylt         break;
43221617c04Sjeremylt       case CEED_OWN_POINTER:
433d979a051Sjeremylt         impl->offsets_allocated = (CeedInt *)offsets;
434d979a051Sjeremylt         impl->offsets           = impl->offsets_allocated;
43521617c04Sjeremylt         break;
43621617c04Sjeremylt       case CEED_USE_POINTER:
437d979a051Sjeremylt         impl->offsets = offsets;
43821617c04Sjeremylt     }
43992fe105eSJeremy L Thompson   }
440fe2413ffSjeremylt 
4412b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionSetData(r, impl));
442d1d35e2fSjeremylt   CeedInt layout[3] = {1, elem_size, elem_size * num_comp};
4432b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionSetELayout(r, layout));
4442b730f8bSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", r, "Apply", CeedElemRestrictionApply_Ref));
445f30b1135SSebastian Grimberg   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", r, "ApplyUnsigned", CeedElemRestrictionApplyUnsigned_Ref));
4462b730f8bSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", r, "ApplyBlock", CeedElemRestrictionApplyBlock_Ref));
4472b730f8bSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", r, "GetOffsets", CeedElemRestrictionGetOffsets_Ref));
448*77d1c127SSebastian Grimberg   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", r, "GetOrientations", CeedElemRestrictionGetOrientations_Ref));
449*77d1c127SSebastian Grimberg   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", r, "GetCurlOrientations", CeedElemRestrictionGetCurlOrientations_Ref));
4502b730f8bSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", r, "Destroy", CeedElemRestrictionDestroy_Ref));
451d979a051Sjeremylt 
452d1d35e2fSjeremylt   // Set apply function based upon num_comp, blk_size, and comp_stride
453d979a051Sjeremylt   CeedInt idx = -1;
4542b730f8bSJeremy L Thompson   if (blk_size < 10) idx = 100 * num_comp + 10 * blk_size + (comp_stride == 1);
455d979a051Sjeremylt   switch (idx) {
456d979a051Sjeremylt     case 110:
457d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_110;
458d979a051Sjeremylt       break;
459d979a051Sjeremylt     case 111:
460d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_111;
461d979a051Sjeremylt       break;
462d979a051Sjeremylt     case 180:
463d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_180;
464d979a051Sjeremylt       break;
465d979a051Sjeremylt     case 181:
466d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_181;
467d979a051Sjeremylt       break;
468d979a051Sjeremylt     case 310:
469d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_310;
470d979a051Sjeremylt       break;
471d979a051Sjeremylt     case 311:
472d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_311;
473d979a051Sjeremylt       break;
474d979a051Sjeremylt     case 380:
475d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_380;
476d979a051Sjeremylt       break;
477d979a051Sjeremylt     case 381:
478d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_381;
479d979a051Sjeremylt       break;
480bf4d1581Sjeremylt     // LCOV_EXCL_START
481d979a051Sjeremylt     case 510:
482d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_510;
483d979a051Sjeremylt       break;
484bf4d1581Sjeremylt     // LCOV_EXCL_STOP
485d979a051Sjeremylt     case 511:
486d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_511;
487d979a051Sjeremylt       break;
488bf4d1581Sjeremylt     // LCOV_EXCL_START
489d979a051Sjeremylt     case 580:
490d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_580;
491d979a051Sjeremylt       break;
492bf4d1581Sjeremylt     // LCOV_EXCL_STOP
493d979a051Sjeremylt     case 581:
494d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_581;
495d979a051Sjeremylt       break;
496d979a051Sjeremylt     default:
497d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_Core;
498d979a051Sjeremylt       break;
499d979a051Sjeremylt   }
500d979a051Sjeremylt 
501e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
50221617c04Sjeremylt }
503fc0567d9Srezgarshakeri 
504fc0567d9Srezgarshakeri //------------------------------------------------------------------------------
505fc0567d9Srezgarshakeri // ElemRestriction Create Oriented
506fc0567d9Srezgarshakeri //------------------------------------------------------------------------------
507*77d1c127SSebastian Grimberg int CeedElemRestrictionCreateOriented_Ref(CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orients,
508fc0567d9Srezgarshakeri                                           CeedElemRestriction r) {
509fc0567d9Srezgarshakeri   // Set up for normal restriction with explicit offsets. This sets up dispatch to
510fc0567d9Srezgarshakeri   // CeedElemRestrictionApply_Ref_* and manages the impl->offsets array copy/allocation.
511*77d1c127SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionCreate_Ref(mem_type, copy_mode, offsets, r));
512*77d1c127SSebastian Grimberg 
513f30b1135SSebastian Grimberg   CeedElemRestriction_Ref *impl;
514f30b1135SSebastian Grimberg   CeedInt                  num_elem, elem_size;
5152b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(r, &impl));
5162b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumElements(r, &num_elem));
5172b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetElementSize(r, &elem_size));
518f30b1135SSebastian Grimberg 
519f30b1135SSebastian Grimberg   // Copy data
520fc0567d9Srezgarshakeri   switch (copy_mode) {
521fc0567d9Srezgarshakeri     case CEED_COPY_VALUES:
522*77d1c127SSebastian Grimberg       CeedCallBackend(CeedMalloc(num_elem * elem_size, &impl->orients_allocated));
523*77d1c127SSebastian Grimberg       memcpy(impl->orients_allocated, orients, num_elem * elem_size * sizeof(orients[0]));
524*77d1c127SSebastian Grimberg       impl->orients = impl->orients_allocated;
525fc0567d9Srezgarshakeri       break;
526fc0567d9Srezgarshakeri     case CEED_OWN_POINTER:
527*77d1c127SSebastian Grimberg       impl->orients_allocated = (bool *)orients;
528*77d1c127SSebastian Grimberg       impl->orients           = impl->orients_allocated;
529fc0567d9Srezgarshakeri       break;
530fc0567d9Srezgarshakeri     case CEED_USE_POINTER:
531*77d1c127SSebastian Grimberg       impl->orients = orients;
532*77d1c127SSebastian Grimberg   }
533*77d1c127SSebastian Grimberg 
534*77d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
535*77d1c127SSebastian Grimberg }
536*77d1c127SSebastian Grimberg 
537*77d1c127SSebastian Grimberg //------------------------------------------------------------------------------
538*77d1c127SSebastian Grimberg // ElemRestriction Create Curl-Conforming Oriented
539*77d1c127SSebastian Grimberg //------------------------------------------------------------------------------
540*77d1c127SSebastian Grimberg int CeedElemRestrictionCreateCurlOriented_Ref(CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const CeedInt *curl_orients,
541*77d1c127SSebastian Grimberg                                               CeedElemRestriction r) {
542*77d1c127SSebastian Grimberg   // Set up for normal restriction with explicit offsets. This sets up dispatch to
543*77d1c127SSebastian Grimberg   // CeedElemRestrictionApply_Ref_* and manages the impl->offsets array copy/allocation.
544*77d1c127SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionCreate_Ref(mem_type, copy_mode, offsets, r));
545*77d1c127SSebastian Grimberg 
546*77d1c127SSebastian Grimberg   CeedElemRestriction_Ref *impl;
547*77d1c127SSebastian Grimberg   CeedInt                  num_elem, elem_size;
548*77d1c127SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetData(r, &impl));
549*77d1c127SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetNumElements(r, &num_elem));
550*77d1c127SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetElementSize(r, &elem_size));
551*77d1c127SSebastian Grimberg 
552*77d1c127SSebastian Grimberg   // Orientation data
553*77d1c127SSebastian Grimberg   switch (copy_mode) {
554*77d1c127SSebastian Grimberg     case CEED_COPY_VALUES:
555*77d1c127SSebastian Grimberg       CeedCallBackend(CeedMalloc(num_elem * 3 * elem_size, &impl->curl_orients_allocated));
556*77d1c127SSebastian Grimberg       memcpy(impl->curl_orients_allocated, curl_orients, num_elem * 3 * elem_size * sizeof(curl_orients[0]));
557*77d1c127SSebastian Grimberg       impl->curl_orients = impl->curl_orients_allocated;
558*77d1c127SSebastian Grimberg       break;
559*77d1c127SSebastian Grimberg     case CEED_OWN_POINTER:
560*77d1c127SSebastian Grimberg       impl->curl_orients_allocated = (CeedInt *)curl_orients;
561*77d1c127SSebastian Grimberg       impl->curl_orients           = impl->curl_orients_allocated;
562*77d1c127SSebastian Grimberg       break;
563*77d1c127SSebastian Grimberg     case CEED_USE_POINTER:
564*77d1c127SSebastian Grimberg       impl->curl_orients = curl_orients;
565fc0567d9Srezgarshakeri   }
566f30b1135SSebastian Grimberg 
567fc0567d9Srezgarshakeri   return CEED_ERROR_SUCCESS;
568fc0567d9Srezgarshakeri }
5692a86cc9dSSebastian Grimberg 
570f10650afSjeremylt //------------------------------------------------------------------------------
571