xref: /libCEED/rust/libceed-sys/c-src/backends/ref/ceed-ref-restriction.c (revision fcbe8c069ccd22d836386af4823e4c7d84ee0a69)
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>
11*fcbe8c06SSebastian Grimberg #include <stdlib.h>
123d576824SJeremy L Thompson #include <string.h>
132b730f8bSJeremy L Thompson 
1421617c04Sjeremylt #include "ceed-ref.h"
1521617c04Sjeremylt 
16f10650afSjeremylt //------------------------------------------------------------------------------
17f10650afSjeremylt // Core ElemRestriction Apply Code
18f10650afSjeremylt //------------------------------------------------------------------------------
192b730f8bSJeremy L Thompson static inline int CeedElemRestrictionApply_Ref_Core(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
2077d1c127SSebastian Grimberg                                                     CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u,
213bdd4e5aSSebastian Grimberg                                                     CeedVector v, CeedRequest *request) {
224ce2993fSjeremylt   CeedElemRestriction_Ref *impl;
232b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(r, &impl));
2421617c04Sjeremylt   const CeedScalar *uu;
2521617c04Sjeremylt   CeedScalar       *vv;
26d1d35e2fSjeremylt   CeedInt           num_elem, elem_size, v_offset;
272b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumElements(r, &num_elem));
282b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetElementSize(r, &elem_size));
29d1d35e2fSjeremylt   v_offset = start * blk_size * elem_size * num_comp;
30*fcbe8c06SSebastian Grimberg   CeedRestrictionType rstr_type;
31*fcbe8c06SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetType(r, &rstr_type));
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
43*fcbe8c06SSebastian Grimberg   // vv has shape [elem_size, num_comp, num_elem], row-major
44*fcbe8c06SSebastian Grimberg   // uu has shape [nnodes, num_comp]
45d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
46*fcbe8c06SSebastian Grimberg     switch (rstr_type) {
47*fcbe8c06SSebastian Grimberg       case CEED_RESTRICTION_STRIDED: {
48d979a051Sjeremylt         // No offsets provided, Identity Restriction
49d1d35e2fSjeremylt         bool has_backend_strides;
502b730f8bSJeremy L Thompson         CeedCallBackend(CeedElemRestrictionHasBackendStrides(r, &has_backend_strides));
51d1d35e2fSjeremylt         if (has_backend_strides) {
52d1d35e2fSjeremylt           // CPU backend strides are {1, elem_size, elem_size*num_comp}
537f90ec76Sjeremylt           // This if branch is left separate to allow better inlining
542b730f8bSJeremy L Thompson           for (CeedInt e = start * blk_size; e < stop * blk_size; e += blk_size) {
552b730f8bSJeremy L Thompson             CeedPragmaSIMD for (CeedInt k = 0; k < num_comp; k++) {
562b730f8bSJeremy L Thompson               CeedPragmaSIMD for (CeedInt n = 0; n < elem_size; n++) {
572b730f8bSJeremy L Thompson                 CeedPragmaSIMD for (CeedInt j = 0; j < blk_size; j++) {
582b730f8bSJeremy L Thompson                   vv[e * elem_size * num_comp + (k * elem_size + n) * blk_size + j - v_offset] =
592b730f8bSJeremy L Thompson                       uu[n + k * elem_size + CeedIntMin(e + j, num_elem - 1) * elem_size * num_comp];
602b730f8bSJeremy L Thompson                 }
612b730f8bSJeremy L Thompson               }
622b730f8bSJeremy L Thompson             }
632b730f8bSJeremy L Thompson           }
647f90ec76Sjeremylt         } else {
657f90ec76Sjeremylt           // User provided strides
667f90ec76Sjeremylt           CeedInt strides[3];
672b730f8bSJeremy L Thompson           CeedCallBackend(CeedElemRestrictionGetStrides(r, &strides));
682b730f8bSJeremy L Thompson           for (CeedInt e = start * blk_size; e < stop * blk_size; e += blk_size) {
692b730f8bSJeremy L Thompson             CeedPragmaSIMD for (CeedInt k = 0; k < num_comp; k++) {
702b730f8bSJeremy L Thompson               CeedPragmaSIMD for (CeedInt n = 0; n < elem_size; n++) {
712b730f8bSJeremy L Thompson                 CeedPragmaSIMD for (CeedInt j = 0; j < blk_size; j++) {
722b730f8bSJeremy L Thompson                   vv[e * elem_size * num_comp + (k * elem_size + n) * blk_size + j - v_offset] =
732b730f8bSJeremy L Thompson                       uu[n * strides[0] + k * strides[1] + CeedIntMin(e + j, num_elem - 1) * strides[2]];
742b730f8bSJeremy L Thompson                 }
752b730f8bSJeremy L Thompson               }
762b730f8bSJeremy L Thompson             }
772b730f8bSJeremy L Thompson           }
787509a596Sjeremylt         }
79*fcbe8c06SSebastian Grimberg       } break;
80*fcbe8c06SSebastian Grimberg       case CEED_RESTRICTION_DEFAULT:
81*fcbe8c06SSebastian Grimberg         // Default restriction with offsets
822b730f8bSJeremy L Thompson         for (CeedInt e = start * blk_size; e < stop * blk_size; e += blk_size) {
832b730f8bSJeremy L Thompson           CeedPragmaSIMD for (CeedInt k = 0; k < num_comp; k++) {
842b730f8bSJeremy L Thompson             CeedPragmaSIMD for (CeedInt i = 0; i < elem_size * blk_size; i++) {
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*fcbe8c06SSebastian Grimberg             }
87*fcbe8c06SSebastian Grimberg           }
88*fcbe8c06SSebastian Grimberg         }
89*fcbe8c06SSebastian Grimberg         break;
90*fcbe8c06SSebastian Grimberg       case CEED_RESTRICTION_ORIENTED:
91*fcbe8c06SSebastian Grimberg         // Restriction with orientations
92*fcbe8c06SSebastian Grimberg         for (CeedInt e = start * blk_size; e < stop * blk_size; e += blk_size) {
93*fcbe8c06SSebastian Grimberg           CeedPragmaSIMD for (CeedInt k = 0; k < num_comp; k++) {
94*fcbe8c06SSebastian Grimberg             CeedPragmaSIMD for (CeedInt i = 0; i < elem_size * blk_size; i++) {
95f30b1135SSebastian Grimberg               vv[elem_size * (k * blk_size + num_comp * e) + i - v_offset] =
96*fcbe8c06SSebastian Grimberg                   uu[impl->offsets[i + elem_size * e] + k * comp_stride] * (use_orients && impl->orients[i + elem_size * e] ? -1.0 : 1.0);
97*fcbe8c06SSebastian Grimberg             }
98*fcbe8c06SSebastian Grimberg           }
99*fcbe8c06SSebastian Grimberg         }
100*fcbe8c06SSebastian Grimberg         break;
101*fcbe8c06SSebastian Grimberg       case CEED_RESTRICTION_CURL_ORIENTED:
10277d1c127SSebastian Grimberg         // Restriction with tridiagonal transformation
103*fcbe8c06SSebastian Grimberg         for (CeedInt e = start * blk_size; e < stop * blk_size; e += blk_size) {
104*fcbe8c06SSebastian Grimberg           CeedPragmaSIMD for (CeedInt k = 0; k < num_comp; k++) {
105*fcbe8c06SSebastian Grimberg             CeedPragmaSIMD for (CeedInt i = 0; i < elem_size * blk_size; i++) {
10677d1c127SSebastian Grimberg               CeedInt ii = i % elem_size;
107*fcbe8c06SSebastian Grimberg               if (use_orients) {
10877d1c127SSebastian Grimberg                 if (ii == 0) {
10977d1c127SSebastian Grimberg                   vv[elem_size * (k * blk_size + num_comp * e) + i - v_offset] =
11077d1c127SSebastian Grimberg                       uu[impl->offsets[i + 0 + elem_size * e] + k * comp_stride] * impl->curl_orients[3 * i + 1 + 3 * elem_size * e] +
11177d1c127SSebastian Grimberg                       uu[impl->offsets[i + 1 + elem_size * e] + k * comp_stride] * impl->curl_orients[3 * i + 2 + 3 * elem_size * e];
11277d1c127SSebastian Grimberg                 } else if (ii == elem_size - 1) {
11377d1c127SSebastian Grimberg                   vv[elem_size * (k * blk_size + num_comp * e) + i - v_offset] =
11477d1c127SSebastian Grimberg                       uu[impl->offsets[i - 1 + elem_size * e] + k * comp_stride] * impl->curl_orients[3 * i + 0 + 3 * elem_size * e] +
11577d1c127SSebastian Grimberg                       uu[impl->offsets[i + 0 + elem_size * e] + k * comp_stride] * impl->curl_orients[3 * i + 1 + 3 * elem_size * e];
11677d1c127SSebastian Grimberg                 } else {
11777d1c127SSebastian Grimberg                   vv[elem_size * (k * blk_size + num_comp * e) + i - v_offset] =
11877d1c127SSebastian Grimberg                       uu[impl->offsets[i - 1 + elem_size * e] + k * comp_stride] * impl->curl_orients[3 * i + 0 + 3 * elem_size * e] +
11977d1c127SSebastian Grimberg                       uu[impl->offsets[i + 0 + elem_size * e] + k * comp_stride] * impl->curl_orients[3 * i + 1 + 3 * elem_size * e] +
12077d1c127SSebastian Grimberg                       uu[impl->offsets[i + 1 + elem_size * e] + k * comp_stride] * impl->curl_orients[3 * i + 2 + 3 * elem_size * e];
12177d1c127SSebastian Grimberg                 }
122*fcbe8c06SSebastian Grimberg               } else {
123*fcbe8c06SSebastian Grimberg                 if (ii == 0) {
124*fcbe8c06SSebastian Grimberg                   vv[elem_size * (k * blk_size + num_comp * e) + i - v_offset] =
125*fcbe8c06SSebastian Grimberg                       uu[impl->offsets[i + 0 + elem_size * e] + k * comp_stride] * abs(impl->curl_orients[3 * i + 1 + 3 * elem_size * e]) +
126*fcbe8c06SSebastian Grimberg                       uu[impl->offsets[i + 1 + elem_size * e] + k * comp_stride] * abs(impl->curl_orients[3 * i + 2 + 3 * elem_size * e]);
127*fcbe8c06SSebastian Grimberg                 } else if (ii == elem_size - 1) {
128*fcbe8c06SSebastian Grimberg                   vv[elem_size * (k * blk_size + num_comp * e) + i - v_offset] =
129*fcbe8c06SSebastian Grimberg                       uu[impl->offsets[i - 1 + elem_size * e] + k * comp_stride] * abs(impl->curl_orients[3 * i + 0 + 3 * elem_size * e]) +
130*fcbe8c06SSebastian Grimberg                       uu[impl->offsets[i + 0 + elem_size * e] + k * comp_stride] * abs(impl->curl_orients[3 * i + 1 + 3 * elem_size * e]);
131*fcbe8c06SSebastian Grimberg                 } else {
132*fcbe8c06SSebastian Grimberg                   vv[elem_size * (k * blk_size + num_comp * e) + i - v_offset] =
133*fcbe8c06SSebastian Grimberg                       uu[impl->offsets[i - 1 + elem_size * e] + k * comp_stride] * abs(impl->curl_orients[3 * i + 0 + 3 * elem_size * e]) +
134*fcbe8c06SSebastian Grimberg                       uu[impl->offsets[i + 0 + elem_size * e] + k * comp_stride] * abs(impl->curl_orients[3 * i + 1 + 3 * elem_size * e]) +
135*fcbe8c06SSebastian Grimberg                       uu[impl->offsets[i + 1 + elem_size * e] + k * comp_stride] * abs(impl->curl_orients[3 * i + 2 + 3 * elem_size * e]);
136f30b1135SSebastian Grimberg                 }
1372b730f8bSJeremy L Thompson               }
1382b730f8bSJeremy L Thompson             }
1392b730f8bSJeremy L Thompson           }
140b435c5a6Srezgarshakeri         }
141*fcbe8c06SSebastian Grimberg         break;
142*fcbe8c06SSebastian Grimberg     }
14321617c04Sjeremylt   } else {
1447f90ec76Sjeremylt     // Restriction from E-vector to L-vector
1458d94b059Sjeremylt     // Performing v += r^T * u
146*fcbe8c06SSebastian Grimberg     // uu has shape [elem_size, num_comp, num_elem]
147*fcbe8c06SSebastian Grimberg     // vv has shape [nnodes, num_comp]
148*fcbe8c06SSebastian Grimberg     switch (rstr_type) {
149*fcbe8c06SSebastian Grimberg       case CEED_RESTRICTION_STRIDED: {
150d979a051Sjeremylt         // No offsets provided, Identity Restriction
151d1d35e2fSjeremylt         bool has_backend_strides;
1522b730f8bSJeremy L Thompson         CeedCallBackend(CeedElemRestrictionHasBackendStrides(r, &has_backend_strides));
153d1d35e2fSjeremylt         if (has_backend_strides) {
154d1d35e2fSjeremylt           // CPU backend strides are {1, elem_size, elem_size*num_comp}
1557f90ec76Sjeremylt           // This if brach is left separate to allow better inlining
1562b730f8bSJeremy L Thompson           for (CeedInt e = start * blk_size; e < stop * blk_size; e += blk_size) {
1572b730f8bSJeremy L Thompson             CeedPragmaSIMD for (CeedInt k = 0; k < num_comp; k++) {
1582b730f8bSJeremy L Thompson               CeedPragmaSIMD for (CeedInt n = 0; n < elem_size; n++) {
1592b730f8bSJeremy L Thompson                 CeedPragmaSIMD for (CeedInt j = 0; j < CeedIntMin(blk_size, num_elem - e); j++) {
1602b730f8bSJeremy L Thompson                   vv[n + k * elem_size + (e + j) * elem_size * num_comp] +=
1612b730f8bSJeremy L Thompson                       uu[e * elem_size * num_comp + (k * elem_size + n) * blk_size + j - v_offset];
1622b730f8bSJeremy L Thompson                 }
1632b730f8bSJeremy L Thompson               }
1642b730f8bSJeremy L Thompson             }
1652b730f8bSJeremy L Thompson           }
1667f90ec76Sjeremylt         } else {
1677f90ec76Sjeremylt           // User provided strides
1687f90ec76Sjeremylt           CeedInt strides[3];
1692b730f8bSJeremy L Thompson           CeedCallBackend(CeedElemRestrictionGetStrides(r, &strides));
1702b730f8bSJeremy L Thompson           for (CeedInt e = start * blk_size; e < stop * blk_size; e += blk_size) {
1712b730f8bSJeremy L Thompson             CeedPragmaSIMD for (CeedInt k = 0; k < num_comp; k++) {
1722b730f8bSJeremy L Thompson               CeedPragmaSIMD for (CeedInt n = 0; n < elem_size; n++) {
1732b730f8bSJeremy L Thompson                 CeedPragmaSIMD for (CeedInt j = 0; j < CeedIntMin(blk_size, num_elem - e); j++) {
1742b730f8bSJeremy L Thompson                   vv[n * strides[0] + k * strides[1] + (e + j) * strides[2]] +=
1752b730f8bSJeremy L Thompson                       uu[e * elem_size * num_comp + (k * elem_size + n) * blk_size + j - v_offset];
1762b730f8bSJeremy L Thompson                 }
1772b730f8bSJeremy L Thompson               }
1782b730f8bSJeremy L Thompson             }
1792b730f8bSJeremy L Thompson           }
180523b8ea0Sjeremylt         }
181*fcbe8c06SSebastian Grimberg       } break;
182*fcbe8c06SSebastian Grimberg       case CEED_RESTRICTION_DEFAULT:
183*fcbe8c06SSebastian Grimberg         // Default restriction with offsets
1842b730f8bSJeremy L Thompson         for (CeedInt e = start * blk_size; e < stop * blk_size; e += blk_size) {
1852b730f8bSJeremy L Thompson           for (CeedInt k = 0; k < num_comp; k++) {
1862b730f8bSJeremy L Thompson             for (CeedInt i = 0; i < elem_size * blk_size; i += blk_size) {
1878d94b059Sjeremylt               // Iteration bound set to discard padding elements
1882b730f8bSJeremy L Thompson               for (CeedInt j = i; j < i + CeedIntMin(blk_size, num_elem - e); j++) {
1893bdd4e5aSSebastian Grimberg                 vv[impl->offsets[j + e * elem_size] + k * comp_stride] += uu[elem_size * (k * blk_size + num_comp * e) + j - v_offset];
190*fcbe8c06SSebastian Grimberg               }
191*fcbe8c06SSebastian Grimberg             }
192*fcbe8c06SSebastian Grimberg           }
193*fcbe8c06SSebastian Grimberg         }
194*fcbe8c06SSebastian Grimberg         break;
195*fcbe8c06SSebastian Grimberg       case CEED_RESTRICTION_ORIENTED:
196*fcbe8c06SSebastian Grimberg         // Restriction with orientations
197*fcbe8c06SSebastian Grimberg         for (CeedInt e = start * blk_size; e < stop * blk_size; e += blk_size) {
198*fcbe8c06SSebastian Grimberg           for (CeedInt k = 0; k < num_comp; k++) {
199*fcbe8c06SSebastian Grimberg             for (CeedInt i = 0; i < elem_size * blk_size; i += blk_size) {
200*fcbe8c06SSebastian Grimberg               // Iteration bound set to discard padding elements
201*fcbe8c06SSebastian Grimberg               for (CeedInt j = i; j < i + CeedIntMin(blk_size, num_elem - e); j++) {
202f30b1135SSebastian Grimberg                 vv[impl->offsets[j + e * elem_size] + k * comp_stride] +=
203*fcbe8c06SSebastian Grimberg                     uu[elem_size * (k * blk_size + num_comp * e) + j - v_offset] * (use_orients && impl->orients[j + e * elem_size] ? -1.0 : 1.0);
204*fcbe8c06SSebastian Grimberg               }
205*fcbe8c06SSebastian Grimberg             }
206*fcbe8c06SSebastian Grimberg           }
207*fcbe8c06SSebastian Grimberg         }
208*fcbe8c06SSebastian Grimberg         break;
209*fcbe8c06SSebastian Grimberg       case CEED_RESTRICTION_CURL_ORIENTED:
21077d1c127SSebastian Grimberg         // Restriction with tridiagonal transformation
211*fcbe8c06SSebastian Grimberg         for (CeedInt e = start * blk_size; e < stop * blk_size; e += blk_size) {
212*fcbe8c06SSebastian Grimberg           for (CeedInt k = 0; k < num_comp; k++) {
213*fcbe8c06SSebastian Grimberg             for (CeedInt i = 0; i < elem_size * blk_size; i += blk_size) {
214*fcbe8c06SSebastian Grimberg               // Iteration bound set to discard padding elements
215*fcbe8c06SSebastian Grimberg               for (CeedInt j = i; j < i + CeedIntMin(blk_size, num_elem - e); j++) {
21677d1c127SSebastian Grimberg                 CeedInt jj = j % elem_size;
217*fcbe8c06SSebastian Grimberg                 if (use_orients) {
21877d1c127SSebastian Grimberg                   if (jj == 0) {
21977d1c127SSebastian Grimberg                     vv[impl->offsets[j + e * elem_size] + k * comp_stride] +=
22077d1c127SSebastian 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] +
22177d1c127SSebastian 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];
22277d1c127SSebastian Grimberg                   } else if (jj == elem_size - 1) {
22377d1c127SSebastian Grimberg                     vv[impl->offsets[j + e * elem_size] + k * comp_stride] +=
22477d1c127SSebastian 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] +
22577d1c127SSebastian 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];
22677d1c127SSebastian Grimberg                   } else {
22777d1c127SSebastian Grimberg                     vv[impl->offsets[j + e * elem_size] + k * comp_stride] +=
22877d1c127SSebastian 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] +
22977d1c127SSebastian 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] +
23077d1c127SSebastian 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];
23177d1c127SSebastian Grimberg                   }
232*fcbe8c06SSebastian Grimberg                 } else {
233*fcbe8c06SSebastian Grimberg                   if (jj == 0) {
234*fcbe8c06SSebastian Grimberg                     vv[impl->offsets[j + e * elem_size] + k * comp_stride] += uu[elem_size * (k * blk_size + num_comp * e) + j + 0 - v_offset] *
235*fcbe8c06SSebastian Grimberg                                                                                   abs(impl->curl_orients[(j + 0) * 3 + 1 + e * 3 * elem_size]) +
236*fcbe8c06SSebastian Grimberg                                                                               uu[elem_size * (k * blk_size + num_comp * e) + j + 1 - v_offset] *
237*fcbe8c06SSebastian Grimberg                                                                                   abs(impl->curl_orients[(j + 1) * 3 + 0 + e * 3 * elem_size]);
238*fcbe8c06SSebastian Grimberg                   } else if (jj == elem_size - 1) {
239*fcbe8c06SSebastian Grimberg                     vv[impl->offsets[j + e * elem_size] + k * comp_stride] += uu[elem_size * (k * blk_size + num_comp * e) + j - 1 - v_offset] *
240*fcbe8c06SSebastian Grimberg                                                                                   abs(impl->curl_orients[(j - 1) * 3 + 2 + e * 3 * elem_size]) +
241*fcbe8c06SSebastian Grimberg                                                                               uu[elem_size * (k * blk_size + num_comp * e) + j + 0 - v_offset] *
242*fcbe8c06SSebastian Grimberg                                                                                   abs(impl->curl_orients[(j + 0) * 3 + 1 + e * 3 * elem_size]);
243*fcbe8c06SSebastian Grimberg                   } else {
244*fcbe8c06SSebastian Grimberg                     vv[impl->offsets[j + e * elem_size] + k * comp_stride] += uu[elem_size * (k * blk_size + num_comp * e) + j - 1 - v_offset] *
245*fcbe8c06SSebastian Grimberg                                                                                   abs(impl->curl_orients[(j - 1) * 3 + 2 + e * 3 * elem_size]) +
246*fcbe8c06SSebastian Grimberg                                                                               uu[elem_size * (k * blk_size + num_comp * e) + j + 0 - v_offset] *
247*fcbe8c06SSebastian Grimberg                                                                                   abs(impl->curl_orients[(j + 0) * 3 + 1 + e * 3 * elem_size]) +
248*fcbe8c06SSebastian Grimberg                                                                               uu[elem_size * (k * blk_size + num_comp * e) + j + 1 - v_offset] *
249*fcbe8c06SSebastian Grimberg                                                                                   abs(impl->curl_orients[(j + 1) * 3 + 0 + e * 3 * elem_size]);
250f30b1135SSebastian Grimberg                   }
25121617c04Sjeremylt                 }
252b435c5a6Srezgarshakeri               }
2532b730f8bSJeremy L Thompson             }
2542b730f8bSJeremy L Thompson           }
2552b730f8bSJeremy L Thompson         }
256*fcbe8c06SSebastian Grimberg         break;
257*fcbe8c06SSebastian Grimberg     }
2582b730f8bSJeremy L Thompson   }
2592b730f8bSJeremy L Thompson   CeedCallBackend(CeedVectorRestoreArrayRead(u, &uu));
2602b730f8bSJeremy L Thompson   CeedCallBackend(CeedVectorRestoreArray(v, &vv));
2612b730f8bSJeremy L Thompson   if (request != CEED_REQUEST_IMMEDIATE && request != CEED_REQUEST_ORDERED) *request = NULL;
262e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
26321617c04Sjeremylt }
26421617c04Sjeremylt 
265f10650afSjeremylt //------------------------------------------------------------------------------
266f10650afSjeremylt // ElemRestriction Apply - Common Sizes
267f10650afSjeremylt //------------------------------------------------------------------------------
2682b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_110(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
26977d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
2703bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
27177d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 1, 1, comp_stride, start, stop, use_orients, t_mode, u, v, request);
272d979a051Sjeremylt }
273d979a051Sjeremylt 
2742b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_111(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
27577d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
2763bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
27777d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 1, 1, 1, start, stop, use_orients, t_mode, u, v, request);
2784d2a38eeSjeremylt }
2794d2a38eeSjeremylt 
2802b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_180(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
28177d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
2823bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
28377d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 1, 8, comp_stride, start, stop, use_orients, t_mode, u, v, request);
2849c36149bSjeremylt }
2859c36149bSjeremylt 
2862b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_181(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
28777d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
2883bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
28977d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 1, 8, 1, start, stop, use_orients, t_mode, u, v, request);
2909c36149bSjeremylt }
2919c36149bSjeremylt 
2922b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_310(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
29377d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
2943bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
29577d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 3, 1, comp_stride, start, stop, use_orients, t_mode, u, v, request);
296d979a051Sjeremylt }
297d979a051Sjeremylt 
2982b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_311(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
29977d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
3003bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
30177d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 3, 1, 1, start, stop, use_orients, t_mode, u, v, request);
302d979a051Sjeremylt }
303d979a051Sjeremylt 
3042b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_380(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
30577d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
3063bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
30777d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 3, 8, comp_stride, start, stop, use_orients, t_mode, u, v, request);
308d979a051Sjeremylt }
309d979a051Sjeremylt 
3102b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_381(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
31177d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
3123bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
31377d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 3, 8, 1, start, stop, use_orients, t_mode, u, v, request);
314d979a051Sjeremylt }
315d979a051Sjeremylt 
316bf4d1581Sjeremylt // LCOV_EXCL_START
3172b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_510(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
31877d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
3193bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
32077d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 5, 1, comp_stride, start, stop, use_orients, t_mode, u, v, request);
321d979a051Sjeremylt }
322bf4d1581Sjeremylt // LCOV_EXCL_STOP
323d979a051Sjeremylt 
3242b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_511(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
32577d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
3263bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
32777d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 5, 1, 1, start, stop, use_orients, t_mode, u, v, request);
328d979a051Sjeremylt }
329d979a051Sjeremylt 
330bf4d1581Sjeremylt // LCOV_EXCL_START
3312b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_580(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
33277d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
3333bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
33477d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 5, 8, comp_stride, start, stop, use_orients, t_mode, u, v, request);
335d979a051Sjeremylt }
336bf4d1581Sjeremylt // LCOV_EXCL_STOP
337d979a051Sjeremylt 
3382b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref_581(CeedElemRestriction r, const CeedInt num_comp, const CeedInt blk_size, const CeedInt comp_stride,
33977d1c127SSebastian Grimberg                                             CeedInt start, CeedInt stop, bool use_orients, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
3403bdd4e5aSSebastian Grimberg                                             CeedRequest *request) {
34177d1c127SSebastian Grimberg   return CeedElemRestrictionApply_Ref_Core(r, 5, 8, 1, start, stop, use_orients, t_mode, u, v, request);
3424d2a38eeSjeremylt }
3434d2a38eeSjeremylt 
344f10650afSjeremylt //------------------------------------------------------------------------------
345f10650afSjeremylt // ElemRestriction Apply
346f10650afSjeremylt //------------------------------------------------------------------------------
3472b730f8bSJeremy L Thompson static int CeedElemRestrictionApply_Ref(CeedElemRestriction r, CeedTransposeMode t_mode, CeedVector u, CeedVector v, CeedRequest *request) {
348d1d35e2fSjeremylt   CeedInt num_blk, blk_size, num_comp, comp_stride;
3492b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumBlocks(r, &num_blk));
3502b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetBlockSize(r, &blk_size));
3512b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumComponents(r, &num_comp));
3522b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCompStride(r, &comp_stride));
3537509a596Sjeremylt   CeedElemRestriction_Ref *impl;
3542b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(r, &impl));
3554d2a38eeSjeremylt 
356f30b1135SSebastian Grimberg   return impl->Apply(r, num_comp, blk_size, comp_stride, 0, num_blk, true, t_mode, u, v, request);
357f30b1135SSebastian Grimberg }
358f30b1135SSebastian Grimberg 
359f30b1135SSebastian Grimberg //------------------------------------------------------------------------------
360f30b1135SSebastian Grimberg // ElemRestriction Apply Unsigned
361f30b1135SSebastian Grimberg //------------------------------------------------------------------------------
362f30b1135SSebastian Grimberg static int CeedElemRestrictionApplyUnsigned_Ref(CeedElemRestriction r, CeedTransposeMode t_mode, CeedVector u, CeedVector v, CeedRequest *request) {
363f30b1135SSebastian Grimberg   CeedInt num_blk, blk_size, num_comp, comp_stride;
364f30b1135SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetNumBlocks(r, &num_blk));
365f30b1135SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetBlockSize(r, &blk_size));
366f30b1135SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetNumComponents(r, &num_comp));
367f30b1135SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetCompStride(r, &comp_stride));
368f30b1135SSebastian Grimberg   CeedElemRestriction_Ref *impl;
369f30b1135SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetData(r, &impl));
370f30b1135SSebastian Grimberg 
371f30b1135SSebastian Grimberg   return impl->Apply(r, num_comp, blk_size, comp_stride, 0, num_blk, false, t_mode, u, v, request);
3729c36149bSjeremylt }
373be9261b7Sjeremylt 
374f10650afSjeremylt //------------------------------------------------------------------------------
375f10650afSjeremylt // ElemRestriction Apply Block
376f10650afSjeremylt //------------------------------------------------------------------------------
3772b730f8bSJeremy L Thompson static int CeedElemRestrictionApplyBlock_Ref(CeedElemRestriction r, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
378074cb416Sjeremylt                                              CeedRequest *request) {
379d1d35e2fSjeremylt   CeedInt blk_size, num_comp, comp_stride;
3802b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetBlockSize(r, &blk_size));
3812b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumComponents(r, &num_comp));
3822b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCompStride(r, &comp_stride));
3837509a596Sjeremylt   CeedElemRestriction_Ref *impl;
3842b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(r, &impl));
3854d2a38eeSjeremylt 
386f30b1135SSebastian Grimberg   return impl->Apply(r, num_comp, blk_size, comp_stride, block, block + 1, true, t_mode, u, v, request);
3879c36149bSjeremylt }
388be9261b7Sjeremylt 
389f10650afSjeremylt //------------------------------------------------------------------------------
390bd33150aSjeremylt // ElemRestriction Get Offsets
391bd33150aSjeremylt //------------------------------------------------------------------------------
3922b730f8bSJeremy L Thompson static int CeedElemRestrictionGetOffsets_Ref(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) {
393bd33150aSjeremylt   CeedElemRestriction_Ref *impl;
3942b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
395bd33150aSjeremylt   Ceed ceed;
3962b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCeed(rstr, &ceed));
397bd33150aSjeremylt 
3986574a04fSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only provide to HOST memory");
399bd33150aSjeremylt 
400bd33150aSjeremylt   *offsets = impl->offsets;
401e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
402bd33150aSjeremylt }
403bd33150aSjeremylt 
404bd33150aSjeremylt //------------------------------------------------------------------------------
40577d1c127SSebastian Grimberg // ElemRestriction Get Orientations
40677d1c127SSebastian Grimberg //------------------------------------------------------------------------------
40777d1c127SSebastian Grimberg static int CeedElemRestrictionGetOrientations_Ref(CeedElemRestriction rstr, CeedMemType mem_type, const bool **orients) {
40877d1c127SSebastian Grimberg   CeedElemRestriction_Ref *impl;
40977d1c127SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
41077d1c127SSebastian Grimberg   Ceed ceed;
41177d1c127SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetCeed(rstr, &ceed));
41277d1c127SSebastian Grimberg 
413*fcbe8c06SSebastian Grimberg   CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only provide to HOST memory");
41477d1c127SSebastian Grimberg 
41577d1c127SSebastian Grimberg   *orients = impl->orients;
41677d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
41777d1c127SSebastian Grimberg }
41877d1c127SSebastian Grimberg 
41977d1c127SSebastian Grimberg //------------------------------------------------------------------------------
42077d1c127SSebastian Grimberg // ElemRestriction Get Curl-Conforming Orientations
42177d1c127SSebastian Grimberg //------------------------------------------------------------------------------
42277d1c127SSebastian Grimberg static int CeedElemRestrictionGetCurlOrientations_Ref(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **curl_orients) {
42377d1c127SSebastian Grimberg   CeedElemRestriction_Ref *impl;
42477d1c127SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
42577d1c127SSebastian Grimberg   Ceed ceed;
42677d1c127SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetCeed(rstr, &ceed));
42777d1c127SSebastian Grimberg 
428*fcbe8c06SSebastian Grimberg   CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only provide to HOST memory");
42977d1c127SSebastian Grimberg 
43077d1c127SSebastian Grimberg   *curl_orients = impl->curl_orients;
43177d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
43277d1c127SSebastian Grimberg }
43377d1c127SSebastian Grimberg 
43477d1c127SSebastian Grimberg //------------------------------------------------------------------------------
435f10650afSjeremylt // ElemRestriction Destroy
436f10650afSjeremylt //------------------------------------------------------------------------------
43721617c04Sjeremylt static int CeedElemRestrictionDestroy_Ref(CeedElemRestriction r) {
438fe2413ffSjeremylt   CeedElemRestriction_Ref *impl;
4392b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(r, &impl));
44021617c04Sjeremylt 
4412b730f8bSJeremy L Thompson   CeedCallBackend(CeedFree(&impl->offsets_allocated));
44277d1c127SSebastian Grimberg   CeedCallBackend(CeedFree(&impl->orients_allocated));
44377d1c127SSebastian Grimberg   CeedCallBackend(CeedFree(&impl->curl_orients_allocated));
4442b730f8bSJeremy L Thompson   CeedCallBackend(CeedFree(&impl));
445e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
44621617c04Sjeremylt }
44721617c04Sjeremylt 
448f10650afSjeremylt //------------------------------------------------------------------------------
449f10650afSjeremylt // ElemRestriction Create
450f10650afSjeremylt //------------------------------------------------------------------------------
451*fcbe8c06SSebastian Grimberg int CeedElemRestrictionCreate_Ref(CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orients,
452*fcbe8c06SSebastian Grimberg                                   const CeedInt *curl_orients, CeedElemRestriction r) {
45321617c04Sjeremylt   CeedElemRestriction_Ref *impl;
454d1d35e2fSjeremylt   CeedInt                  num_elem, elem_size, num_blk, blk_size, num_comp, comp_stride;
4552b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumElements(r, &num_elem));
4562b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetElementSize(r, &elem_size));
4572b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumBlocks(r, &num_blk));
4582b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetBlockSize(r, &blk_size));
4592b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumComponents(r, &num_comp));
4602b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCompStride(r, &comp_stride));
4614ce2993fSjeremylt   Ceed ceed;
4622b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCeed(r, &ceed));
46321617c04Sjeremylt 
4646574a04fSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Only MemType = HOST supported");
4652b730f8bSJeremy L Thompson   CeedCallBackend(CeedCalloc(1, &impl));
4663661185eSjeremylt 
46792fe105eSJeremy L Thompson   // Offsets data
468*fcbe8c06SSebastian Grimberg   CeedRestrictionType rstr_type;
469*fcbe8c06SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetType(r, &rstr_type));
470*fcbe8c06SSebastian Grimberg   if (rstr_type != CEED_RESTRICTION_STRIDED) {
47192fe105eSJeremy L Thompson     // Check indices for ref or memcheck backends
472d1d35e2fSjeremylt     Ceed parent_ceed = ceed, curr_ceed = NULL;
473d1d35e2fSjeremylt     while (parent_ceed != curr_ceed) {
474d1d35e2fSjeremylt       curr_ceed = parent_ceed;
4752b730f8bSJeremy L Thompson       CeedCallBackend(CeedGetParent(curr_ceed, &parent_ceed));
4763661185eSjeremylt     }
4773661185eSjeremylt     const char *resource;
4782b730f8bSJeremy L Thompson     CeedCallBackend(CeedGetResource(parent_ceed, &resource));
4792b730f8bSJeremy L Thompson     if (!strcmp(resource, "/cpu/self/ref/serial") || !strcmp(resource, "/cpu/self/ref/blocked") || !strcmp(resource, "/cpu/self/memcheck/serial") ||
480d1d35e2fSjeremylt         !strcmp(resource, "/cpu/self/memcheck/blocked")) {
481e79b91d9SJeremy L Thompson       CeedSize l_size;
4822b730f8bSJeremy L Thompson       CeedCallBackend(CeedElemRestrictionGetLVectorSize(r, &l_size));
4833661185eSjeremylt 
4842b730f8bSJeremy L Thompson       for (CeedInt i = 0; i < num_elem * elem_size; i++) {
4856574a04fSJeremy L Thompson         CeedCheck(offsets[i] >= 0 && offsets[i] + (num_comp - 1) * comp_stride < l_size, ceed, CEED_ERROR_BACKEND,
4866574a04fSJeremy L Thompson                   "Restriction offset %" CeedInt_FMT " (%" CeedInt_FMT ") out of range [0, %" CeedInt_FMT "]", i, offsets[i], l_size);
4872b730f8bSJeremy L Thompson       }
4882b730f8bSJeremy L Thompson     }
4893661185eSjeremylt 
49092fe105eSJeremy L Thompson     // Copy data
491d1d35e2fSjeremylt     switch (copy_mode) {
49221617c04Sjeremylt       case CEED_COPY_VALUES:
4932b730f8bSJeremy L Thompson         CeedCallBackend(CeedMalloc(num_elem * elem_size, &impl->offsets_allocated));
4942b730f8bSJeremy L Thompson         memcpy(impl->offsets_allocated, offsets, num_elem * elem_size * sizeof(offsets[0]));
495d979a051Sjeremylt         impl->offsets = impl->offsets_allocated;
49621617c04Sjeremylt         break;
49721617c04Sjeremylt       case CEED_OWN_POINTER:
498d979a051Sjeremylt         impl->offsets_allocated = (CeedInt *)offsets;
499d979a051Sjeremylt         impl->offsets           = impl->offsets_allocated;
50021617c04Sjeremylt         break;
50121617c04Sjeremylt       case CEED_USE_POINTER:
502d979a051Sjeremylt         impl->offsets = offsets;
50321617c04Sjeremylt     }
504*fcbe8c06SSebastian Grimberg 
505*fcbe8c06SSebastian Grimberg     // Orientation data
506*fcbe8c06SSebastian Grimberg     if (rstr_type == CEED_RESTRICTION_ORIENTED) {
507*fcbe8c06SSebastian Grimberg       switch (copy_mode) {
508*fcbe8c06SSebastian Grimberg         case CEED_COPY_VALUES:
509*fcbe8c06SSebastian Grimberg           CeedCallBackend(CeedMalloc(num_elem * elem_size, &impl->orients_allocated));
510*fcbe8c06SSebastian Grimberg           memcpy(impl->orients_allocated, orients, num_elem * elem_size * sizeof(orients[0]));
511*fcbe8c06SSebastian Grimberg           impl->orients = impl->orients_allocated;
512*fcbe8c06SSebastian Grimberg           break;
513*fcbe8c06SSebastian Grimberg         case CEED_OWN_POINTER:
514*fcbe8c06SSebastian Grimberg           impl->orients_allocated = (bool *)orients;
515*fcbe8c06SSebastian Grimberg           impl->orients           = impl->orients_allocated;
516*fcbe8c06SSebastian Grimberg           break;
517*fcbe8c06SSebastian Grimberg         case CEED_USE_POINTER:
518*fcbe8c06SSebastian Grimberg           impl->orients = orients;
519*fcbe8c06SSebastian Grimberg       }
520*fcbe8c06SSebastian Grimberg     } else if (rstr_type == CEED_RESTRICTION_CURL_ORIENTED) {
521*fcbe8c06SSebastian Grimberg       switch (copy_mode) {
522*fcbe8c06SSebastian Grimberg         case CEED_COPY_VALUES:
523*fcbe8c06SSebastian Grimberg           CeedCallBackend(CeedMalloc(num_elem * 3 * elem_size, &impl->curl_orients_allocated));
524*fcbe8c06SSebastian Grimberg           memcpy(impl->curl_orients_allocated, curl_orients, num_elem * 3 * elem_size * sizeof(curl_orients[0]));
525*fcbe8c06SSebastian Grimberg           impl->curl_orients = impl->curl_orients_allocated;
526*fcbe8c06SSebastian Grimberg           break;
527*fcbe8c06SSebastian Grimberg         case CEED_OWN_POINTER:
528*fcbe8c06SSebastian Grimberg           impl->curl_orients_allocated = (CeedInt *)curl_orients;
529*fcbe8c06SSebastian Grimberg           impl->curl_orients           = impl->curl_orients_allocated;
530*fcbe8c06SSebastian Grimberg           break;
531*fcbe8c06SSebastian Grimberg         case CEED_USE_POINTER:
532*fcbe8c06SSebastian Grimberg           impl->curl_orients = curl_orients;
533*fcbe8c06SSebastian Grimberg       }
534*fcbe8c06SSebastian Grimberg     }
53592fe105eSJeremy L Thompson   }
536fe2413ffSjeremylt 
5372b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionSetData(r, impl));
538d1d35e2fSjeremylt   CeedInt layout[3] = {1, elem_size, elem_size * num_comp};
5392b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionSetELayout(r, layout));
5402b730f8bSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", r, "Apply", CeedElemRestrictionApply_Ref));
541f30b1135SSebastian Grimberg   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", r, "ApplyUnsigned", CeedElemRestrictionApplyUnsigned_Ref));
5422b730f8bSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", r, "ApplyBlock", CeedElemRestrictionApplyBlock_Ref));
5432b730f8bSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", r, "GetOffsets", CeedElemRestrictionGetOffsets_Ref));
54477d1c127SSebastian Grimberg   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", r, "GetOrientations", CeedElemRestrictionGetOrientations_Ref));
54577d1c127SSebastian Grimberg   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", r, "GetCurlOrientations", CeedElemRestrictionGetCurlOrientations_Ref));
5462b730f8bSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", r, "Destroy", CeedElemRestrictionDestroy_Ref));
547d979a051Sjeremylt 
548d1d35e2fSjeremylt   // Set apply function based upon num_comp, blk_size, and comp_stride
549d979a051Sjeremylt   CeedInt idx = -1;
5502b730f8bSJeremy L Thompson   if (blk_size < 10) idx = 100 * num_comp + 10 * blk_size + (comp_stride == 1);
551d979a051Sjeremylt   switch (idx) {
552d979a051Sjeremylt     case 110:
553d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_110;
554d979a051Sjeremylt       break;
555d979a051Sjeremylt     case 111:
556d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_111;
557d979a051Sjeremylt       break;
558d979a051Sjeremylt     case 180:
559d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_180;
560d979a051Sjeremylt       break;
561d979a051Sjeremylt     case 181:
562d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_181;
563d979a051Sjeremylt       break;
564d979a051Sjeremylt     case 310:
565d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_310;
566d979a051Sjeremylt       break;
567d979a051Sjeremylt     case 311:
568d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_311;
569d979a051Sjeremylt       break;
570d979a051Sjeremylt     case 380:
571d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_380;
572d979a051Sjeremylt       break;
573d979a051Sjeremylt     case 381:
574d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_381;
575d979a051Sjeremylt       break;
576bf4d1581Sjeremylt     // LCOV_EXCL_START
577d979a051Sjeremylt     case 510:
578d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_510;
579d979a051Sjeremylt       break;
580bf4d1581Sjeremylt     // LCOV_EXCL_STOP
581d979a051Sjeremylt     case 511:
582d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_511;
583d979a051Sjeremylt       break;
584bf4d1581Sjeremylt     // LCOV_EXCL_START
585d979a051Sjeremylt     case 580:
586d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_580;
587d979a051Sjeremylt       break;
588bf4d1581Sjeremylt     // LCOV_EXCL_STOP
589d979a051Sjeremylt     case 581:
590d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_581;
591d979a051Sjeremylt       break;
592d979a051Sjeremylt     default:
593d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_Core;
594d979a051Sjeremylt       break;
595d979a051Sjeremylt   }
596d979a051Sjeremylt 
597e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
59821617c04Sjeremylt }
599fc0567d9Srezgarshakeri 
600fc0567d9Srezgarshakeri //------------------------------------------------------------------------------
601