xref: /libCEED/rust/libceed-sys/c-src/backends/ref/ceed-ref-restriction.c (revision 2c7e74134068de5221afb7e7255d8033016bfd12)
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>
11fcbe8c06SSebastian 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 //------------------------------------------------------------------------------
191cc2c60dSJeremy L Thompson static inline int CeedElemRestrictionApplyStridedNoTranspose_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size,
2094648b7dSSebastian Grimberg                                                                       CeedInt start, CeedInt stop, CeedInt num_elem, CeedInt elem_size,
2194648b7dSSebastian Grimberg                                                                       CeedInt v_offset, const CeedScalar *uu, CeedScalar *vv) {
2294648b7dSSebastian Grimberg   // No offsets provided, identity restriction
23d1d35e2fSjeremylt   bool has_backend_strides;
24ad70ee2cSJeremy L Thompson 
251cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionHasBackendStrides(rstr, &has_backend_strides));
26d1d35e2fSjeremylt   if (has_backend_strides) {
27d1d35e2fSjeremylt     // CPU backend strides are {1, elem_size, elem_size*num_comp}
287f90ec76Sjeremylt     // This if branch is left separate to allow better inlining
29ad70ee2cSJeremy L Thompson     for (CeedInt e = start * block_size; e < stop * block_size; e += block_size) {
302b730f8bSJeremy L Thompson       CeedPragmaSIMD for (CeedInt k = 0; k < num_comp; k++) {
312b730f8bSJeremy L Thompson         CeedPragmaSIMD for (CeedInt n = 0; n < elem_size; n++) {
32ad70ee2cSJeremy L Thompson           CeedPragmaSIMD for (CeedInt j = 0; j < block_size; j++) {
33ad70ee2cSJeremy L Thompson             vv[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] =
342b730f8bSJeremy L Thompson                 uu[n + k * elem_size + CeedIntMin(e + j, num_elem - 1) * elem_size * num_comp];
352b730f8bSJeremy L Thompson           }
362b730f8bSJeremy L Thompson         }
372b730f8bSJeremy L Thompson       }
382b730f8bSJeremy L Thompson     }
397f90ec76Sjeremylt   } else {
407f90ec76Sjeremylt     // User provided strides
417f90ec76Sjeremylt     CeedInt strides[3];
42ad70ee2cSJeremy L Thompson 
431cc2c60dSJeremy L Thompson     CeedCallBackend(CeedElemRestrictionGetStrides(rstr, &strides));
44ad70ee2cSJeremy L Thompson     for (CeedInt e = start * block_size; e < stop * block_size; e += block_size) {
452b730f8bSJeremy L Thompson       CeedPragmaSIMD for (CeedInt k = 0; k < num_comp; k++) {
462b730f8bSJeremy L Thompson         CeedPragmaSIMD for (CeedInt n = 0; n < elem_size; n++) {
47ad70ee2cSJeremy L Thompson           CeedPragmaSIMD for (CeedInt j = 0; j < block_size; j++) {
48ad70ee2cSJeremy L Thompson             vv[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] =
492b730f8bSJeremy L Thompson                 uu[n * strides[0] + k * strides[1] + CeedIntMin(e + j, num_elem - 1) * strides[2]];
502b730f8bSJeremy L Thompson           }
512b730f8bSJeremy L Thompson         }
522b730f8bSJeremy L Thompson       }
532b730f8bSJeremy L Thompson     }
547509a596Sjeremylt   }
5594648b7dSSebastian Grimberg   return CEED_ERROR_SUCCESS;
5694648b7dSSebastian Grimberg }
5794648b7dSSebastian Grimberg 
581cc2c60dSJeremy L Thompson static inline int CeedElemRestrictionApplyStandardNoTranspose_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size,
5994648b7dSSebastian Grimberg                                                                        const CeedInt comp_stride, CeedInt start, CeedInt stop, CeedInt num_elem,
6094648b7dSSebastian Grimberg                                                                        CeedInt elem_size, CeedInt v_offset, const CeedScalar *uu, CeedScalar *vv) {
61fcbe8c06SSebastian Grimberg   // Default restriction with offsets
6294648b7dSSebastian Grimberg   CeedElemRestriction_Ref *impl;
63ad70ee2cSJeremy L Thompson 
641cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
65ad70ee2cSJeremy L Thompson   for (CeedInt e = start * block_size; e < stop * block_size; e += block_size) {
662b730f8bSJeremy L Thompson     CeedPragmaSIMD for (CeedInt k = 0; k < num_comp; k++) {
67ad70ee2cSJeremy L Thompson       CeedPragmaSIMD for (CeedInt i = 0; i < elem_size * block_size; i++) {
68ad70ee2cSJeremy L Thompson         vv[elem_size * (k * block_size + e * num_comp) + i - v_offset] = uu[impl->offsets[i + e * elem_size] + k * comp_stride];
69fcbe8c06SSebastian Grimberg       }
70fcbe8c06SSebastian Grimberg     }
71fcbe8c06SSebastian Grimberg   }
7294648b7dSSebastian Grimberg   return CEED_ERROR_SUCCESS;
7394648b7dSSebastian Grimberg }
7494648b7dSSebastian Grimberg 
751cc2c60dSJeremy L Thompson static inline int CeedElemRestrictionApplyOrientedNoTranspose_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size,
7694648b7dSSebastian Grimberg                                                                        const CeedInt comp_stride, CeedInt start, CeedInt stop, CeedInt num_elem,
7794648b7dSSebastian Grimberg                                                                        CeedInt elem_size, CeedInt v_offset, const CeedScalar *uu, CeedScalar *vv) {
78fcbe8c06SSebastian Grimberg   // Restriction with orientations
7994648b7dSSebastian Grimberg   CeedElemRestriction_Ref *impl;
80ad70ee2cSJeremy L Thompson 
811cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
82ad70ee2cSJeremy L Thompson   for (CeedInt e = start * block_size; e < stop * block_size; e += block_size) {
83fcbe8c06SSebastian Grimberg     CeedPragmaSIMD for (CeedInt k = 0; k < num_comp; k++) {
84ad70ee2cSJeremy L Thompson       CeedPragmaSIMD for (CeedInt i = 0; i < elem_size * block_size; i++) {
85ad70ee2cSJeremy L Thompson         vv[elem_size * (k * block_size + e * num_comp) + i - v_offset] =
867c1dbaffSSebastian Grimberg             uu[impl->offsets[i + e * elem_size] + k * comp_stride] * (impl->orients[i + e * elem_size] ? -1.0 : 1.0);
87fcbe8c06SSebastian Grimberg       }
88fcbe8c06SSebastian Grimberg     }
89fcbe8c06SSebastian Grimberg   }
9094648b7dSSebastian Grimberg   return CEED_ERROR_SUCCESS;
9194648b7dSSebastian Grimberg }
9294648b7dSSebastian Grimberg 
931cc2c60dSJeremy L Thompson static inline int CeedElemRestrictionApplyCurlOrientedNoTranspose_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size,
9494648b7dSSebastian Grimberg                                                                            const CeedInt comp_stride, CeedInt start, CeedInt stop, CeedInt num_elem,
9594648b7dSSebastian Grimberg                                                                            CeedInt elem_size, CeedInt v_offset, const CeedScalar *uu,
9694648b7dSSebastian Grimberg                                                                            CeedScalar *vv) {
9777d1c127SSebastian Grimberg   // Restriction with tridiagonal transformation
9894648b7dSSebastian Grimberg   CeedElemRestriction_Ref *impl;
99ad70ee2cSJeremy L Thompson 
1001cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
101ad70ee2cSJeremy L Thompson   for (CeedInt e = start * block_size; e < stop * block_size; e += block_size) {
102fcbe8c06SSebastian Grimberg     CeedPragmaSIMD for (CeedInt k = 0; k < num_comp; k++) {
1030c73c039SSebastian Grimberg       CeedInt n = 0;
104ad70ee2cSJeremy L Thompson       CeedPragmaSIMD for (CeedInt j = 0; j < block_size; j++) {
105ad70ee2cSJeremy L Thompson         vv[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] =
106ad70ee2cSJeremy L Thompson             uu[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] *
107ad70ee2cSJeremy L Thompson                 impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size] +
108ad70ee2cSJeremy L Thompson             uu[impl->offsets[j + (n + 1) * block_size + e * elem_size] + k * comp_stride] *
109ad70ee2cSJeremy L Thompson                 impl->curl_orients[j + (3 * n + 2) * block_size + e * 3 * elem_size];
1100c73c039SSebastian Grimberg       }
1110c73c039SSebastian Grimberg       for (n = 1; n < elem_size - 1; n++) {
112ad70ee2cSJeremy L Thompson         CeedPragmaSIMD for (CeedInt j = 0; j < block_size; j++) {
113ad70ee2cSJeremy L Thompson           vv[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] =
114ad70ee2cSJeremy L Thompson               uu[impl->offsets[j + (n - 1) * block_size + e * elem_size] + k * comp_stride] *
115ad70ee2cSJeremy L Thompson                   impl->curl_orients[j + (3 * n + 0) * block_size + e * 3 * elem_size] +
116ad70ee2cSJeremy L Thompson               uu[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] *
117ad70ee2cSJeremy L Thompson                   impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size] +
118ad70ee2cSJeremy L Thompson               uu[impl->offsets[j + (n + 1) * block_size + e * elem_size] + k * comp_stride] *
119ad70ee2cSJeremy L Thompson                   impl->curl_orients[j + (3 * n + 2) * block_size + e * 3 * elem_size];
1200c73c039SSebastian Grimberg         }
1210c73c039SSebastian Grimberg       }
122ad70ee2cSJeremy L Thompson       CeedPragmaSIMD for (CeedInt j = 0; j < block_size; j++) {
123ad70ee2cSJeremy L Thompson         vv[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] =
124ad70ee2cSJeremy L Thompson             uu[impl->offsets[j + (n - 1) * block_size + e * elem_size] + k * comp_stride] *
125ad70ee2cSJeremy L Thompson                 impl->curl_orients[j + (3 * n + 0) * block_size + e * 3 * elem_size] +
126ad70ee2cSJeremy L Thompson             uu[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] *
127ad70ee2cSJeremy L Thompson                 impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size];
1282b730f8bSJeremy L Thompson       }
1292b730f8bSJeremy L Thompson     }
1302b730f8bSJeremy L Thompson   }
1310c73c039SSebastian Grimberg   return CEED_ERROR_SUCCESS;
132fcbe8c06SSebastian Grimberg }
1330c73c039SSebastian Grimberg 
1341cc2c60dSJeremy L Thompson static inline int CeedElemRestrictionApplyCurlOrientedUnsignedNoTranspose_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp,
135ad70ee2cSJeremy L Thompson                                                                                    const CeedInt block_size, const CeedInt comp_stride, CeedInt start,
13694648b7dSSebastian Grimberg                                                                                    CeedInt stop, CeedInt num_elem, CeedInt elem_size,
13794648b7dSSebastian Grimberg                                                                                    CeedInt v_offset, const CeedScalar *uu, CeedScalar *vv) {
13894648b7dSSebastian Grimberg   // Restriction with (unsigned) tridiagonal transformation
1390c73c039SSebastian Grimberg   CeedElemRestriction_Ref *impl;
140ad70ee2cSJeremy L Thompson 
1411cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
142ad70ee2cSJeremy L Thompson   for (CeedInt e = start * block_size; e < stop * block_size; e += block_size) {
1437c1dbaffSSebastian Grimberg     CeedPragmaSIMD for (CeedInt k = 0; k < num_comp; k++) {
1447c1dbaffSSebastian Grimberg       CeedInt n = 0;
145ad70ee2cSJeremy L Thompson 
146ad70ee2cSJeremy L Thompson       CeedPragmaSIMD for (CeedInt j = 0; j < block_size; j++) {
147ad70ee2cSJeremy L Thompson         vv[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] =
148ad70ee2cSJeremy L Thompson             uu[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] *
149ad70ee2cSJeremy L Thompson                 abs(impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size]) +
150ad70ee2cSJeremy L Thompson             uu[impl->offsets[j + (n + 1) * block_size + e * elem_size] + k * comp_stride] *
151ad70ee2cSJeremy L Thompson                 abs(impl->curl_orients[j + (3 * n + 2) * block_size + e * 3 * elem_size]);
1527c1dbaffSSebastian Grimberg       }
1537c1dbaffSSebastian Grimberg       for (n = 1; n < elem_size - 1; n++) {
154ad70ee2cSJeremy L Thompson         CeedPragmaSIMD for (CeedInt j = 0; j < block_size; j++) {
155ad70ee2cSJeremy L Thompson           vv[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] =
156ad70ee2cSJeremy L Thompson               uu[impl->offsets[j + (n - 1) * block_size + e * elem_size] + k * comp_stride] *
157ad70ee2cSJeremy L Thompson                   abs(impl->curl_orients[j + (3 * n + 0) * block_size + e * 3 * elem_size]) +
158ad70ee2cSJeremy L Thompson               uu[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] *
159ad70ee2cSJeremy L Thompson                   abs(impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size]) +
160ad70ee2cSJeremy L Thompson               uu[impl->offsets[j + (n + 1) * block_size + e * elem_size] + k * comp_stride] *
161ad70ee2cSJeremy L Thompson                   abs(impl->curl_orients[j + (3 * n + 2) * block_size + e * 3 * elem_size]);
1627c1dbaffSSebastian Grimberg         }
1637c1dbaffSSebastian Grimberg       }
164ad70ee2cSJeremy L Thompson       CeedPragmaSIMD for (CeedInt j = 0; j < block_size; j++) {
165ad70ee2cSJeremy L Thompson         vv[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] =
166ad70ee2cSJeremy L Thompson             uu[impl->offsets[j + (n - 1) * block_size + e * elem_size] + k * comp_stride] *
167ad70ee2cSJeremy L Thompson                 abs(impl->curl_orients[j + (3 * n + 0) * block_size + e * 3 * elem_size]) +
168ad70ee2cSJeremy L Thompson             uu[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] *
169ad70ee2cSJeremy L Thompson                 abs(impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size]);
1707c1dbaffSSebastian Grimberg       }
1717c1dbaffSSebastian Grimberg     }
1727c1dbaffSSebastian Grimberg   }
1737c1dbaffSSebastian Grimberg   return CEED_ERROR_SUCCESS;
1747c1dbaffSSebastian Grimberg }
1757c1dbaffSSebastian Grimberg 
1761cc2c60dSJeremy L Thompson static inline int CeedElemRestrictionApplyStridedTranspose_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size,
17794648b7dSSebastian Grimberg                                                                     CeedInt start, CeedInt stop, CeedInt num_elem, CeedInt elem_size,
17894648b7dSSebastian Grimberg                                                                     CeedInt v_offset, const CeedScalar *uu, CeedScalar *vv) {
17994648b7dSSebastian Grimberg   // No offsets provided, identity restriction
180d1d35e2fSjeremylt   bool has_backend_strides;
181ad70ee2cSJeremy L Thompson 
1821cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionHasBackendStrides(rstr, &has_backend_strides));
183d1d35e2fSjeremylt   if (has_backend_strides) {
184d1d35e2fSjeremylt     // CPU backend strides are {1, elem_size, elem_size*num_comp}
1857f90ec76Sjeremylt     // This if brach is left separate to allow better inlining
186ad70ee2cSJeremy L Thompson     for (CeedInt e = start * block_size; e < stop * block_size; e += block_size) {
1872b730f8bSJeremy L Thompson       CeedPragmaSIMD for (CeedInt k = 0; k < num_comp; k++) {
1882b730f8bSJeremy L Thompson         CeedPragmaSIMD for (CeedInt n = 0; n < elem_size; n++) {
189ad70ee2cSJeremy L Thompson           CeedPragmaSIMD for (CeedInt j = 0; j < CeedIntMin(block_size, num_elem - e); j++) {
190ad70ee2cSJeremy L Thompson             vv[n + k * elem_size + (e + j) * elem_size * num_comp] += uu[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset];
1912b730f8bSJeremy L Thompson           }
1922b730f8bSJeremy L Thompson         }
1932b730f8bSJeremy L Thompson       }
1942b730f8bSJeremy L Thompson     }
1957f90ec76Sjeremylt   } else {
1967f90ec76Sjeremylt     // User provided strides
1977f90ec76Sjeremylt     CeedInt strides[3];
198ad70ee2cSJeremy L Thompson 
1991cc2c60dSJeremy L Thompson     CeedCallBackend(CeedElemRestrictionGetStrides(rstr, &strides));
200ad70ee2cSJeremy L Thompson     for (CeedInt e = start * block_size; e < stop * block_size; e += block_size) {
2012b730f8bSJeremy L Thompson       CeedPragmaSIMD for (CeedInt k = 0; k < num_comp; k++) {
2022b730f8bSJeremy L Thompson         CeedPragmaSIMD for (CeedInt n = 0; n < elem_size; n++) {
203ad70ee2cSJeremy L Thompson           CeedPragmaSIMD for (CeedInt j = 0; j < CeedIntMin(block_size, num_elem - e); j++) {
2042b730f8bSJeremy L Thompson             vv[n * strides[0] + k * strides[1] + (e + j) * strides[2]] +=
205ad70ee2cSJeremy L Thompson                 uu[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset];
2062b730f8bSJeremy L Thompson           }
2072b730f8bSJeremy L Thompson         }
2082b730f8bSJeremy L Thompson       }
2092b730f8bSJeremy L Thompson     }
210523b8ea0Sjeremylt   }
21194648b7dSSebastian Grimberg   return CEED_ERROR_SUCCESS;
21294648b7dSSebastian Grimberg }
21394648b7dSSebastian Grimberg 
2141cc2c60dSJeremy L Thompson static inline int CeedElemRestrictionApplyStandardTranspose_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size,
21594648b7dSSebastian Grimberg                                                                      const CeedInt comp_stride, CeedInt start, CeedInt stop, CeedInt num_elem,
21694648b7dSSebastian Grimberg                                                                      CeedInt elem_size, CeedInt v_offset, const CeedScalar *uu, CeedScalar *vv) {
217fcbe8c06SSebastian Grimberg   // Default restriction with offsets
21894648b7dSSebastian Grimberg   CeedElemRestriction_Ref *impl;
219ad70ee2cSJeremy L Thompson 
2201cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
221ad70ee2cSJeremy L Thompson   for (CeedInt e = start * block_size; e < stop * block_size; e += block_size) {
2222b730f8bSJeremy L Thompson     for (CeedInt k = 0; k < num_comp; k++) {
223ad70ee2cSJeremy L Thompson       for (CeedInt i = 0; i < elem_size * block_size; i += block_size) {
2248d94b059Sjeremylt         // Iteration bound set to discard padding elements
225ad70ee2cSJeremy L Thompson         for (CeedInt j = i; j < i + CeedIntMin(block_size, num_elem - e); j++) {
226ad70ee2cSJeremy L Thompson           vv[impl->offsets[j + e * elem_size] + k * comp_stride] += uu[elem_size * (k * block_size + e * num_comp) + j - v_offset];
227fcbe8c06SSebastian Grimberg         }
228fcbe8c06SSebastian Grimberg       }
229fcbe8c06SSebastian Grimberg     }
230fcbe8c06SSebastian Grimberg   }
23194648b7dSSebastian Grimberg   return CEED_ERROR_SUCCESS;
23294648b7dSSebastian Grimberg }
23394648b7dSSebastian Grimberg 
2341cc2c60dSJeremy L Thompson static inline int CeedElemRestrictionApplyOrientedTranspose_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size,
23594648b7dSSebastian Grimberg                                                                      const CeedInt comp_stride, CeedInt start, CeedInt stop, CeedInt num_elem,
23694648b7dSSebastian Grimberg                                                                      CeedInt elem_size, CeedInt v_offset, const CeedScalar *uu, CeedScalar *vv) {
237fcbe8c06SSebastian Grimberg   // Restriction with orientations
23894648b7dSSebastian Grimberg   CeedElemRestriction_Ref *impl;
239ad70ee2cSJeremy L Thompson 
2401cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
241ad70ee2cSJeremy L Thompson   for (CeedInt e = start * block_size; e < stop * block_size; e += block_size) {
242fcbe8c06SSebastian Grimberg     for (CeedInt k = 0; k < num_comp; k++) {
243ad70ee2cSJeremy L Thompson       for (CeedInt i = 0; i < elem_size * block_size; i += block_size) {
244fcbe8c06SSebastian Grimberg         // Iteration bound set to discard padding elements
245ad70ee2cSJeremy L Thompson         for (CeedInt j = i; j < i + CeedIntMin(block_size, num_elem - e); j++) {
246f30b1135SSebastian Grimberg           vv[impl->offsets[j + e * elem_size] + k * comp_stride] +=
247ad70ee2cSJeremy L Thompson               uu[elem_size * (k * block_size + e * num_comp) + j - v_offset] * (impl->orients[j + e * elem_size] ? -1.0 : 1.0);
248fcbe8c06SSebastian Grimberg         }
249fcbe8c06SSebastian Grimberg       }
250fcbe8c06SSebastian Grimberg     }
251fcbe8c06SSebastian Grimberg   }
25294648b7dSSebastian Grimberg   return CEED_ERROR_SUCCESS;
25394648b7dSSebastian Grimberg }
25494648b7dSSebastian Grimberg 
2551cc2c60dSJeremy L Thompson static inline int CeedElemRestrictionApplyCurlOrientedTranspose_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size,
25694648b7dSSebastian Grimberg                                                                          const CeedInt comp_stride, CeedInt start, CeedInt stop, CeedInt num_elem,
25794648b7dSSebastian Grimberg                                                                          CeedInt elem_size, CeedInt v_offset, const CeedScalar *uu, CeedScalar *vv) {
25877d1c127SSebastian Grimberg   // Restriction with tridiagonal transformation
25994648b7dSSebastian Grimberg   CeedElemRestriction_Ref *impl;
260ad70ee2cSJeremy L Thompson 
2611cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
262ad70ee2cSJeremy L Thompson   for (CeedInt e = start * block_size; e < stop * block_size; e += block_size) {
263fcbe8c06SSebastian Grimberg     for (CeedInt k = 0; k < num_comp; k++) {
264fcbe8c06SSebastian Grimberg       // Iteration bound set to discard padding elements
265ad70ee2cSJeremy L Thompson       CeedInt block_end = CeedIntMin(block_size, num_elem - e), n = 0;
266ad70ee2cSJeremy L Thompson       for (CeedInt j = 0; j < block_end; j++) {
267ad70ee2cSJeremy L Thompson         vv[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] +=
268ad70ee2cSJeremy L Thompson             uu[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] *
269ad70ee2cSJeremy L Thompson                 impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size] +
270ad70ee2cSJeremy L Thompson             uu[e * elem_size * num_comp + (k * elem_size + n + 1) * block_size + j - v_offset] *
271ad70ee2cSJeremy L Thompson                 impl->curl_orients[j + (3 * n + 3) * block_size + e * 3 * elem_size];
2720c73c039SSebastian Grimberg       }
2730c73c039SSebastian Grimberg       for (n = 1; n < elem_size - 1; n++) {
274ad70ee2cSJeremy L Thompson         for (CeedInt j = 0; j < block_end; j++) {
275ad70ee2cSJeremy L Thompson           vv[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] +=
276ad70ee2cSJeremy L Thompson               uu[e * elem_size * num_comp + (k * elem_size + n - 1) * block_size + j - v_offset] *
277ad70ee2cSJeremy L Thompson                   impl->curl_orients[j + (3 * n - 1) * block_size + e * 3 * elem_size] +
278ad70ee2cSJeremy L Thompson               uu[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] *
279ad70ee2cSJeremy L Thompson                   impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size] +
280ad70ee2cSJeremy L Thompson               uu[e * elem_size * num_comp + (k * elem_size + n + 1) * block_size + j - v_offset] *
281ad70ee2cSJeremy L Thompson                   impl->curl_orients[j + (3 * n + 3) * block_size + e * 3 * elem_size];
2820c73c039SSebastian Grimberg         }
2830c73c039SSebastian Grimberg       }
284ad70ee2cSJeremy L Thompson       for (CeedInt j = 0; j < block_end; j++) {
285ad70ee2cSJeremy L Thompson         vv[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] +=
286ad70ee2cSJeremy L Thompson             uu[e * elem_size * num_comp + (k * elem_size + n - 1) * block_size + j - v_offset] *
287ad70ee2cSJeremy L Thompson                 impl->curl_orients[j + (3 * n - 1) * block_size + e * 3 * elem_size] +
288ad70ee2cSJeremy L Thompson             uu[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] *
289ad70ee2cSJeremy L Thompson                 impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size];
29021617c04Sjeremylt       }
291b435c5a6Srezgarshakeri     }
2922b730f8bSJeremy L Thompson   }
293e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
29421617c04Sjeremylt }
29521617c04Sjeremylt 
2961cc2c60dSJeremy L Thompson static inline int CeedElemRestrictionApplyCurlOrientedUnsignedTranspose_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp,
297ad70ee2cSJeremy L Thompson                                                                                  const CeedInt block_size, const CeedInt comp_stride, CeedInt start,
29894648b7dSSebastian Grimberg                                                                                  CeedInt stop, CeedInt num_elem, CeedInt elem_size, CeedInt v_offset,
29994648b7dSSebastian Grimberg                                                                                  const CeedScalar *uu, CeedScalar *vv) {
30094648b7dSSebastian Grimberg   // Restriction with (unsigned) tridiagonal transformation
3017c1dbaffSSebastian Grimberg   CeedElemRestriction_Ref *impl;
302ad70ee2cSJeremy L Thompson 
3031cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
304ad70ee2cSJeremy L Thompson   for (CeedInt e = start * block_size; e < stop * block_size; e += block_size) {
3057c1dbaffSSebastian Grimberg     for (CeedInt k = 0; k < num_comp; k++) {
3067c1dbaffSSebastian Grimberg       // Iteration bound set to discard padding elements
307ad70ee2cSJeremy L Thompson       CeedInt       n         = 0;
308ad70ee2cSJeremy L Thompson       const CeedInt block_end = CeedIntMin(block_size, num_elem - e);
309ad70ee2cSJeremy L Thompson 
310ad70ee2cSJeremy L Thompson       for (CeedInt j = 0; j < block_end; j++) {
311ad70ee2cSJeremy L Thompson         vv[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] +=
312ad70ee2cSJeremy L Thompson             uu[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] *
313ad70ee2cSJeremy L Thompson                 abs(impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size]) +
314ad70ee2cSJeremy L Thompson             uu[e * elem_size * num_comp + (k * elem_size + n + 1) * block_size + j - v_offset] *
315ad70ee2cSJeremy L Thompson                 abs(impl->curl_orients[j + (3 * n + 3) * block_size + e * 3 * elem_size]);
3167c1dbaffSSebastian Grimberg       }
3177c1dbaffSSebastian Grimberg       for (n = 1; n < elem_size - 1; n++) {
318ad70ee2cSJeremy L Thompson         for (CeedInt j = 0; j < block_end; j++) {
319ad70ee2cSJeremy L Thompson           vv[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] +=
320ad70ee2cSJeremy L Thompson               uu[e * elem_size * num_comp + (k * elem_size + n - 1) * block_size + j - v_offset] *
321ad70ee2cSJeremy L Thompson                   abs(impl->curl_orients[j + (3 * n - 1) * block_size + e * 3 * elem_size]) +
322ad70ee2cSJeremy L Thompson               uu[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] *
323ad70ee2cSJeremy L Thompson                   abs(impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size]) +
324ad70ee2cSJeremy L Thompson               uu[e * elem_size * num_comp + (k * elem_size + n + 1) * block_size + j - v_offset] *
325ad70ee2cSJeremy L Thompson                   abs(impl->curl_orients[j + (3 * n + 3) * block_size + e * 3 * elem_size]);
3267c1dbaffSSebastian Grimberg         }
3277c1dbaffSSebastian Grimberg       }
328ad70ee2cSJeremy L Thompson       for (CeedInt j = 0; j < block_end; j++) {
329ad70ee2cSJeremy L Thompson         vv[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] +=
330ad70ee2cSJeremy L Thompson             uu[e * elem_size * num_comp + (k * elem_size + n - 1) * block_size + j - v_offset] *
331ad70ee2cSJeremy L Thompson                 abs(impl->curl_orients[j + (3 * n - 1) * block_size + e * 3 * elem_size]) +
332ad70ee2cSJeremy L Thompson             uu[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] *
333ad70ee2cSJeremy L Thompson                 abs(impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size]);
3347c1dbaffSSebastian Grimberg       }
3357c1dbaffSSebastian Grimberg     }
3367c1dbaffSSebastian Grimberg   }
3377c1dbaffSSebastian Grimberg   return CEED_ERROR_SUCCESS;
3387c1dbaffSSebastian Grimberg }
3397c1dbaffSSebastian Grimberg 
3401cc2c60dSJeremy L Thompson static inline int CeedElemRestrictionApply_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size,
341ad70ee2cSJeremy L Thompson                                                     const CeedInt comp_stride, CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs,
342ad70ee2cSJeremy L Thompson                                                     bool use_orients, CeedVector u, CeedVector v, CeedRequest *request) {
343ad70ee2cSJeremy L Thompson   CeedInt             num_elem, elem_size, v_offset;
344ad70ee2cSJeremy L Thompson   CeedRestrictionType rstr_type;
3457c1dbaffSSebastian Grimberg   const CeedScalar   *uu;
3467c1dbaffSSebastian Grimberg   CeedScalar         *vv;
347ad70ee2cSJeremy L Thompson 
3481cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumElements(rstr, &num_elem));
3491cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetElementSize(rstr, &elem_size));
350ad70ee2cSJeremy L Thompson   v_offset = start * block_size * elem_size * num_comp;
3511cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetType(rstr, &rstr_type));
35294648b7dSSebastian Grimberg   CeedCallBackend(CeedVectorGetArrayRead(u, CEED_MEM_HOST, &uu));
353ad70ee2cSJeremy L Thompson 
35494648b7dSSebastian Grimberg   if (t_mode == CEED_TRANSPOSE) {
35594648b7dSSebastian Grimberg     // Sum into for transpose mode, E-vector to L-vector
35694648b7dSSebastian Grimberg     CeedCallBackend(CeedVectorGetArray(v, CEED_MEM_HOST, &vv));
35794648b7dSSebastian Grimberg   } else {
35894648b7dSSebastian Grimberg     // Overwrite for notranspose mode, L-vector to E-vector
35994648b7dSSebastian Grimberg     CeedCallBackend(CeedVectorGetArrayWrite(v, CEED_MEM_HOST, &vv));
36094648b7dSSebastian Grimberg   }
36194648b7dSSebastian Grimberg   if (t_mode == CEED_TRANSPOSE) {
3627c1dbaffSSebastian Grimberg     // Restriction from E-vector to L-vector
3637c1dbaffSSebastian Grimberg     // Performing v += r^T * u
3647c1dbaffSSebastian Grimberg     // uu has shape [elem_size, num_comp, num_elem], row-major
3657c1dbaffSSebastian Grimberg     // vv has shape [nnodes, num_comp]
3667c1dbaffSSebastian Grimberg     // Sum into for transpose mode
3677c1dbaffSSebastian Grimberg     switch (rstr_type) {
3687c1dbaffSSebastian Grimberg       case CEED_RESTRICTION_STRIDED:
3695d10938bSJeremy L Thompson         CeedCallBackend(
3701cc2c60dSJeremy L Thompson             CeedElemRestrictionApplyStridedTranspose_Ref_Core(rstr, num_comp, block_size, start, stop, num_elem, elem_size, v_offset, uu, vv));
37194648b7dSSebastian Grimberg         break;
37261a27d74SSebastian Grimberg       case CEED_RESTRICTION_STANDARD:
3731cc2c60dSJeremy L Thompson         CeedCallBackend(CeedElemRestrictionApplyStandardTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop, num_elem, elem_size,
3745d10938bSJeremy L Thompson                                                                            v_offset, uu, vv));
37594648b7dSSebastian Grimberg         break;
3767c1dbaffSSebastian Grimberg       case CEED_RESTRICTION_ORIENTED:
37794648b7dSSebastian Grimberg         if (use_signs) {
3781cc2c60dSJeremy L Thompson           CeedCallBackend(CeedElemRestrictionApplyOrientedTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop, num_elem,
3791cc2c60dSJeremy L Thompson                                                                              elem_size, v_offset, uu, vv));
38094648b7dSSebastian Grimberg         } else {
3811cc2c60dSJeremy L Thompson           CeedCallBackend(CeedElemRestrictionApplyStandardTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop, num_elem,
3821cc2c60dSJeremy L Thompson                                                                              elem_size, v_offset, uu, vv));
38394648b7dSSebastian Grimberg         }
38494648b7dSSebastian Grimberg         break;
38594648b7dSSebastian Grimberg       case CEED_RESTRICTION_CURL_ORIENTED:
38694648b7dSSebastian Grimberg         if (use_signs && use_orients) {
3871cc2c60dSJeremy L Thompson           CeedCallBackend(CeedElemRestrictionApplyCurlOrientedTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop, num_elem,
3885d10938bSJeremy L Thompson                                                                                  elem_size, v_offset, uu, vv));
38994648b7dSSebastian Grimberg         } else if (use_orients) {
3901cc2c60dSJeremy L Thompson           CeedCallBackend(CeedElemRestrictionApplyCurlOrientedUnsignedTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop,
3911cc2c60dSJeremy L Thompson                                                                                          num_elem, elem_size, v_offset, uu, vv));
39294648b7dSSebastian Grimberg         } else {
3931cc2c60dSJeremy L Thompson           CeedCallBackend(CeedElemRestrictionApplyStandardTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop, num_elem,
3941cc2c60dSJeremy L Thompson                                                                              elem_size, v_offset, uu, vv));
39594648b7dSSebastian Grimberg         }
39694648b7dSSebastian Grimberg         break;
397*2c7e7413SJeremy L Thompson       case CEED_RESTRICTION_POINTS:
398*2c7e7413SJeremy L Thompson         // Empty case - won't occur
399*2c7e7413SJeremy L Thompson         break;
40094648b7dSSebastian Grimberg     }
40194648b7dSSebastian Grimberg   } else {
40294648b7dSSebastian Grimberg     // Restriction from L-vector to E-vector
40394648b7dSSebastian Grimberg     // Perform: v = r * u
40494648b7dSSebastian Grimberg     // vv has shape [elem_size, num_comp, num_elem], row-major
40594648b7dSSebastian Grimberg     // uu has shape [nnodes, num_comp]
40694648b7dSSebastian Grimberg     // Overwrite for notranspose mode
40794648b7dSSebastian Grimberg     switch (rstr_type) {
40894648b7dSSebastian Grimberg       case CEED_RESTRICTION_STRIDED:
4095d10938bSJeremy L Thompson         CeedCallBackend(
4101cc2c60dSJeremy L Thompson             CeedElemRestrictionApplyStridedNoTranspose_Ref_Core(rstr, num_comp, block_size, start, stop, num_elem, elem_size, v_offset, uu, vv));
41194648b7dSSebastian Grimberg         break;
41261a27d74SSebastian Grimberg       case CEED_RESTRICTION_STANDARD:
4131cc2c60dSJeremy L Thompson         CeedCallBackend(CeedElemRestrictionApplyStandardNoTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop, num_elem,
4141cc2c60dSJeremy L Thompson                                                                              elem_size, v_offset, uu, vv));
41594648b7dSSebastian Grimberg         break;
41694648b7dSSebastian Grimberg       case CEED_RESTRICTION_ORIENTED:
41794648b7dSSebastian Grimberg         if (use_signs) {
4181cc2c60dSJeremy L Thompson           CeedCallBackend(CeedElemRestrictionApplyOrientedNoTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop, num_elem,
4191cc2c60dSJeremy L Thompson                                                                                elem_size, v_offset, uu, vv));
42094648b7dSSebastian Grimberg         } else {
4211cc2c60dSJeremy L Thompson           CeedCallBackend(CeedElemRestrictionApplyStandardNoTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop, num_elem,
4221cc2c60dSJeremy L Thompson                                                                                elem_size, v_offset, uu, vv));
42394648b7dSSebastian Grimberg         }
42494648b7dSSebastian Grimberg         break;
42594648b7dSSebastian Grimberg       case CEED_RESTRICTION_CURL_ORIENTED:
42694648b7dSSebastian Grimberg         if (use_signs && use_orients) {
4271cc2c60dSJeremy L Thompson           CeedCallBackend(CeedElemRestrictionApplyCurlOrientedNoTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop, num_elem,
4285d10938bSJeremy L Thompson                                                                                    elem_size, v_offset, uu, vv));
42994648b7dSSebastian Grimberg         } else if (use_orients) {
4301cc2c60dSJeremy L Thompson           CeedCallBackend(CeedElemRestrictionApplyCurlOrientedUnsignedNoTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop,
4315d10938bSJeremy L Thompson                                                                                            num_elem, elem_size, v_offset, uu, vv));
43294648b7dSSebastian Grimberg         } else {
4331cc2c60dSJeremy L Thompson           CeedCallBackend(CeedElemRestrictionApplyStandardNoTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop, num_elem,
4341cc2c60dSJeremy L Thompson                                                                                elem_size, v_offset, uu, vv));
43594648b7dSSebastian Grimberg         }
43694648b7dSSebastian Grimberg         break;
437*2c7e7413SJeremy L Thompson       case CEED_RESTRICTION_POINTS:
438*2c7e7413SJeremy L Thompson         // Empty case - won't occur
439*2c7e7413SJeremy L Thompson         break;
44094648b7dSSebastian Grimberg     }
4417c1dbaffSSebastian Grimberg   }
4427c1dbaffSSebastian Grimberg   CeedCallBackend(CeedVectorRestoreArrayRead(u, &uu));
4437c1dbaffSSebastian Grimberg   CeedCallBackend(CeedVectorRestoreArray(v, &vv));
4447c1dbaffSSebastian Grimberg   if (request != CEED_REQUEST_IMMEDIATE && request != CEED_REQUEST_ORDERED) *request = NULL;
4457c1dbaffSSebastian Grimberg   return CEED_ERROR_SUCCESS;
4467c1dbaffSSebastian Grimberg }
4477c1dbaffSSebastian Grimberg 
4487c1dbaffSSebastian Grimberg //------------------------------------------------------------------------------
449f10650afSjeremylt // ElemRestriction Apply - Common Sizes
450f10650afSjeremylt //------------------------------------------------------------------------------
4511cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_110(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
4527c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
4537c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
4541cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 1, 1, comp_stride, start, stop, t_mode, use_signs, use_orients, u, v, request);
455d979a051Sjeremylt }
456d979a051Sjeremylt 
4571cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_111(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
4587c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
4597c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
4601cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 1, 1, 1, start, stop, t_mode, use_signs, use_orients, u, v, request);
4614d2a38eeSjeremylt }
4624d2a38eeSjeremylt 
4631cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_180(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
4647c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
4657c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
4661cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 1, 8, comp_stride, start, stop, t_mode, use_signs, use_orients, u, v, request);
4679c36149bSjeremylt }
4689c36149bSjeremylt 
4691cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_181(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
4707c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
4717c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
4721cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 1, 8, 1, start, stop, t_mode, use_signs, use_orients, u, v, request);
4739c36149bSjeremylt }
4749c36149bSjeremylt 
4751cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_310(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
4767c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
4777c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
4781cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 3, 1, comp_stride, start, stop, t_mode, use_signs, use_orients, u, v, request);
479d979a051Sjeremylt }
480d979a051Sjeremylt 
4811cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_311(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
4827c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
4837c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
4841cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 3, 1, 1, start, stop, t_mode, use_signs, use_orients, u, v, request);
485d979a051Sjeremylt }
486d979a051Sjeremylt 
4871cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_380(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
4887c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
4897c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
4901cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 3, 8, comp_stride, start, stop, t_mode, use_signs, use_orients, u, v, request);
491d979a051Sjeremylt }
492d979a051Sjeremylt 
4931cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_381(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
4947c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
4957c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
4961cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 3, 8, 1, start, stop, t_mode, use_signs, use_orients, u, v, request);
497d979a051Sjeremylt }
498d979a051Sjeremylt 
499bf4d1581Sjeremylt // LCOV_EXCL_START
5001cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_510(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
5017c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
5027c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
5031cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 5, 1, comp_stride, start, stop, t_mode, use_signs, use_orients, u, v, request);
504d979a051Sjeremylt }
505bf4d1581Sjeremylt // LCOV_EXCL_STOP
506d979a051Sjeremylt 
5071cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_511(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
5087c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
5097c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
5101cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 5, 1, 1, start, stop, t_mode, use_signs, use_orients, u, v, request);
511d979a051Sjeremylt }
512d979a051Sjeremylt 
513bf4d1581Sjeremylt // LCOV_EXCL_START
5141cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_580(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
5157c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
5167c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
5171cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 5, 8, comp_stride, start, stop, t_mode, use_signs, use_orients, u, v, request);
518d979a051Sjeremylt }
519bf4d1581Sjeremylt // LCOV_EXCL_STOP
520d979a051Sjeremylt 
5211cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_581(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
5227c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
5230c73c039SSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
5241cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 5, 8, 1, start, stop, t_mode, use_signs, use_orients, u, v, request);
5254d2a38eeSjeremylt }
5264d2a38eeSjeremylt 
527f10650afSjeremylt //------------------------------------------------------------------------------
528f10650afSjeremylt // ElemRestriction Apply
529f10650afSjeremylt //------------------------------------------------------------------------------
5301cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector v, CeedRequest *request) {
531ad70ee2cSJeremy L Thompson   CeedInt                  num_block, block_size, num_comp, comp_stride;
532ad70ee2cSJeremy L Thompson   CeedElemRestriction_Ref *impl;
533ad70ee2cSJeremy L Thompson 
5341cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumBlocks(rstr, &num_block));
5351cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetBlockSize(rstr, &block_size));
5361cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
5371cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCompStride(rstr, &comp_stride));
5381cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
5391cc2c60dSJeremy L Thompson   CeedCallBackend(impl->Apply(rstr, num_comp, block_size, comp_stride, 0, num_block, t_mode, true, true, u, v, request));
5405d10938bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
541f30b1135SSebastian Grimberg }
542f30b1135SSebastian Grimberg 
543f30b1135SSebastian Grimberg //------------------------------------------------------------------------------
544f30b1135SSebastian Grimberg // ElemRestriction Apply Unsigned
545f30b1135SSebastian Grimberg //------------------------------------------------------------------------------
5461cc2c60dSJeremy L Thompson static int CeedElemRestrictionApplyUnsigned_Ref(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
5471cc2c60dSJeremy L Thompson                                                 CeedRequest *request) {
548ad70ee2cSJeremy L Thompson   CeedInt                  num_block, block_size, num_comp, comp_stride;
549ad70ee2cSJeremy L Thompson   CeedElemRestriction_Ref *impl;
550ad70ee2cSJeremy L Thompson 
5511cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumBlocks(rstr, &num_block));
5521cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetBlockSize(rstr, &block_size));
5531cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
5541cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCompStride(rstr, &comp_stride));
5551cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
5561cc2c60dSJeremy L Thompson   CeedCallBackend(impl->Apply(rstr, num_comp, block_size, comp_stride, 0, num_block, t_mode, false, true, u, v, request));
5575d10938bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
5587c1dbaffSSebastian Grimberg }
5597c1dbaffSSebastian Grimberg 
5607c1dbaffSSebastian Grimberg //------------------------------------------------------------------------------
5617c1dbaffSSebastian Grimberg // ElemRestriction Apply Unoriented
5627c1dbaffSSebastian Grimberg //------------------------------------------------------------------------------
5631cc2c60dSJeremy L Thompson static int CeedElemRestrictionApplyUnoriented_Ref(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
5641cc2c60dSJeremy L Thompson                                                   CeedRequest *request) {
565ad70ee2cSJeremy L Thompson   CeedInt                  num_block, block_size, num_comp, comp_stride;
566ad70ee2cSJeremy L Thompson   CeedElemRestriction_Ref *impl;
567ad70ee2cSJeremy L Thompson 
5681cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumBlocks(rstr, &num_block));
5691cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetBlockSize(rstr, &block_size));
5701cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
5711cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCompStride(rstr, &comp_stride));
5721cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
5731cc2c60dSJeremy L Thompson   CeedCallBackend(impl->Apply(rstr, num_comp, block_size, comp_stride, 0, num_block, t_mode, false, false, u, v, request));
5745d10938bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
5759c36149bSjeremylt }
576be9261b7Sjeremylt 
577f10650afSjeremylt //------------------------------------------------------------------------------
578*2c7e7413SJeremy L Thompson // ElemRestriction Apply Points
579*2c7e7413SJeremy L Thompson //------------------------------------------------------------------------------
580*2c7e7413SJeremy L Thompson static int CeedElemRestrictionApplyAtPoints_Ref(CeedElemRestriction r, CeedInt elem, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
581*2c7e7413SJeremy L Thompson                                                 CeedRequest *request) {
582*2c7e7413SJeremy L Thompson   CeedInt                  num_points, num_comp, l_vec_offset;
583*2c7e7413SJeremy L Thompson   CeedScalar              *vv;
584*2c7e7413SJeremy L Thompson   const CeedScalar        *uu;
585*2c7e7413SJeremy L Thompson   CeedElemRestriction_Ref *impl;
586*2c7e7413SJeremy L Thompson 
587*2c7e7413SJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(r, &impl));
588*2c7e7413SJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumComponents(r, &num_comp));
589*2c7e7413SJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumPointsInElement(r, elem, &num_points));
590*2c7e7413SJeremy L Thompson 
591*2c7e7413SJeremy L Thompson   CeedCallBackend(CeedVectorGetArrayRead(u, CEED_MEM_HOST, &uu));
592*2c7e7413SJeremy L Thompson   if (t_mode == CEED_TRANSPOSE) {
593*2c7e7413SJeremy L Thompson     // Sum into for transpose mode, E-vector to L-vector
594*2c7e7413SJeremy L Thompson     CeedCallBackend(CeedVectorGetArray(v, CEED_MEM_HOST, &vv));
595*2c7e7413SJeremy L Thompson   } else {
596*2c7e7413SJeremy L Thompson     // Overwrite for notranspose mode, L-vector to E-vector
597*2c7e7413SJeremy L Thompson     CeedCallBackend(CeedVectorGetArrayWrite(v, CEED_MEM_HOST, &vv));
598*2c7e7413SJeremy L Thompson   }
599*2c7e7413SJeremy L Thompson 
600*2c7e7413SJeremy L Thompson   l_vec_offset = impl->offsets[elem + 1] - impl->offsets[elem];
601*2c7e7413SJeremy L Thompson   if (t_mode == CEED_NOTRANSPOSE) {
602*2c7e7413SJeremy L Thompson     for (CeedInt i = 0; i < num_points; i++) {
603*2c7e7413SJeremy L Thompson       for (CeedInt j = 0; j < num_comp; j++) vv[i * num_comp + j] = uu[impl->offsets[i + l_vec_offset] * num_comp + j];
604*2c7e7413SJeremy L Thompson     }
605*2c7e7413SJeremy L Thompson   } else {
606*2c7e7413SJeremy L Thompson     for (CeedInt i = 0; i < num_points; i++) {
607*2c7e7413SJeremy L Thompson       for (CeedInt j = 0; j < num_comp; j++) vv[impl->offsets[i + l_vec_offset] * num_comp + j] = uu[i * num_comp + j];
608*2c7e7413SJeremy L Thompson     }
609*2c7e7413SJeremy L Thompson   }
610*2c7e7413SJeremy L Thompson 
611*2c7e7413SJeremy L Thompson   return CEED_ERROR_SUCCESS;
612*2c7e7413SJeremy L Thompson }
613*2c7e7413SJeremy L Thompson 
614*2c7e7413SJeremy L Thompson //------------------------------------------------------------------------------
615f10650afSjeremylt // ElemRestriction Apply Block
616f10650afSjeremylt //------------------------------------------------------------------------------
6171cc2c60dSJeremy L Thompson static int CeedElemRestrictionApplyBlock_Ref(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
618074cb416Sjeremylt                                              CeedRequest *request) {
619ad70ee2cSJeremy L Thompson   CeedInt                  block_size, num_comp, comp_stride;
620ad70ee2cSJeremy L Thompson   CeedElemRestriction_Ref *impl;
621ad70ee2cSJeremy L Thompson 
6221cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetBlockSize(rstr, &block_size));
6231cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
6241cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCompStride(rstr, &comp_stride));
6251cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
6261cc2c60dSJeremy L Thompson   CeedCallBackend(impl->Apply(rstr, num_comp, block_size, comp_stride, block, block + 1, t_mode, true, true, u, v, request));
6275d10938bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
6289c36149bSjeremylt }
629be9261b7Sjeremylt 
630f10650afSjeremylt //------------------------------------------------------------------------------
631bd33150aSjeremylt // ElemRestriction Get Offsets
632bd33150aSjeremylt //------------------------------------------------------------------------------
6332b730f8bSJeremy L Thompson static int CeedElemRestrictionGetOffsets_Ref(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) {
634bd33150aSjeremylt   Ceed                     ceed;
635ad70ee2cSJeremy L Thompson   CeedElemRestriction_Ref *impl;
636ad70ee2cSJeremy L Thompson 
637ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
6382b730f8bSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCeed(rstr, &ceed));
639bd33150aSjeremylt 
6406574a04fSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only provide to HOST memory");
641bd33150aSjeremylt 
642bd33150aSjeremylt   *offsets = impl->offsets;
643e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
644bd33150aSjeremylt }
645bd33150aSjeremylt 
646bd33150aSjeremylt //------------------------------------------------------------------------------
64777d1c127SSebastian Grimberg // ElemRestriction Get Orientations
64877d1c127SSebastian Grimberg //------------------------------------------------------------------------------
64977d1c127SSebastian Grimberg static int CeedElemRestrictionGetOrientations_Ref(CeedElemRestriction rstr, CeedMemType mem_type, const bool **orients) {
65077d1c127SSebastian Grimberg   Ceed                     ceed;
651ad70ee2cSJeremy L Thompson   CeedElemRestriction_Ref *impl;
652ad70ee2cSJeremy L Thompson 
653ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
65477d1c127SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetCeed(rstr, &ceed));
65577d1c127SSebastian Grimberg 
656fcbe8c06SSebastian Grimberg   CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only provide to HOST memory");
65777d1c127SSebastian Grimberg 
65877d1c127SSebastian Grimberg   *orients = impl->orients;
65977d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
66077d1c127SSebastian Grimberg }
66177d1c127SSebastian Grimberg 
66277d1c127SSebastian Grimberg //------------------------------------------------------------------------------
66377d1c127SSebastian Grimberg // ElemRestriction Get Curl-Conforming Orientations
66477d1c127SSebastian Grimberg //------------------------------------------------------------------------------
6650c73c039SSebastian Grimberg static int CeedElemRestrictionGetCurlOrientations_Ref(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt8 **curl_orients) {
66677d1c127SSebastian Grimberg   Ceed                     ceed;
667ad70ee2cSJeremy L Thompson   CeedElemRestriction_Ref *impl;
668ad70ee2cSJeremy L Thompson 
669ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
67077d1c127SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetCeed(rstr, &ceed));
67177d1c127SSebastian Grimberg 
672fcbe8c06SSebastian Grimberg   CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only provide to HOST memory");
67377d1c127SSebastian Grimberg 
67477d1c127SSebastian Grimberg   *curl_orients = impl->curl_orients;
67577d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
67677d1c127SSebastian Grimberg }
67777d1c127SSebastian Grimberg 
67877d1c127SSebastian Grimberg //------------------------------------------------------------------------------
679f10650afSjeremylt // ElemRestriction Destroy
680f10650afSjeremylt //------------------------------------------------------------------------------
6811cc2c60dSJeremy L Thompson static int CeedElemRestrictionDestroy_Ref(CeedElemRestriction rstr) {
682fe2413ffSjeremylt   CeedElemRestriction_Ref *impl;
68321617c04Sjeremylt 
6841cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
6852b730f8bSJeremy L Thompson   CeedCallBackend(CeedFree(&impl->offsets_allocated));
68677d1c127SSebastian Grimberg   CeedCallBackend(CeedFree(&impl->orients_allocated));
68777d1c127SSebastian Grimberg   CeedCallBackend(CeedFree(&impl->curl_orients_allocated));
6882b730f8bSJeremy L Thompson   CeedCallBackend(CeedFree(&impl));
689e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
69021617c04Sjeremylt }
69121617c04Sjeremylt 
692f10650afSjeremylt //------------------------------------------------------------------------------
693f10650afSjeremylt // ElemRestriction Create
694f10650afSjeremylt //------------------------------------------------------------------------------
695fcbe8c06SSebastian Grimberg int CeedElemRestrictionCreate_Ref(CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orients,
6961cc2c60dSJeremy L Thompson                                   const CeedInt8 *curl_orients, CeedElemRestriction rstr) {
697ad70ee2cSJeremy L Thompson   Ceed                     ceed;
698ad70ee2cSJeremy L Thompson   CeedInt                  num_elem, elem_size, num_block, block_size, num_comp, comp_stride;
699ad70ee2cSJeremy L Thompson   CeedRestrictionType      rstr_type;
70021617c04Sjeremylt   CeedElemRestriction_Ref *impl;
701ad70ee2cSJeremy L Thompson 
7021cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCeed(rstr, &ceed));
7031cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumElements(rstr, &num_elem));
7041cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetElementSize(rstr, &elem_size));
7051cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumBlocks(rstr, &num_block));
7061cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetBlockSize(rstr, &block_size));
7071cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
7081cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCompStride(rstr, &comp_stride));
709ad70ee2cSJeremy L Thompson   CeedInt layout[3] = {1, elem_size, elem_size * num_comp};
71021617c04Sjeremylt 
7116574a04fSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Only MemType = HOST supported");
7122b730f8bSJeremy L Thompson   CeedCallBackend(CeedCalloc(1, &impl));
7133661185eSjeremylt 
71492fe105eSJeremy L Thompson   // Offsets data
7151cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetType(rstr, &rstr_type));
716fcbe8c06SSebastian Grimberg   if (rstr_type != CEED_RESTRICTION_STRIDED) {
7173661185eSjeremylt     const char *resource;
718ad70ee2cSJeremy L Thompson 
719ad70ee2cSJeremy L Thompson     // Check indices for ref or memcheck backends
720ad70ee2cSJeremy L Thompson     CeedCallBackend(CeedGetResource(ceed, &resource));
7212b730f8bSJeremy L Thompson     if (!strcmp(resource, "/cpu/self/ref/serial") || !strcmp(resource, "/cpu/self/ref/blocked") || !strcmp(resource, "/cpu/self/memcheck/serial") ||
722d1d35e2fSjeremylt         !strcmp(resource, "/cpu/self/memcheck/blocked")) {
723e79b91d9SJeremy L Thompson       CeedSize l_size;
7243661185eSjeremylt 
7251cc2c60dSJeremy L Thompson       CeedCallBackend(CeedElemRestrictionGetLVectorSize(rstr, &l_size));
7262b730f8bSJeremy L Thompson       for (CeedInt i = 0; i < num_elem * elem_size; i++) {
7276574a04fSJeremy L Thompson         CeedCheck(offsets[i] >= 0 && offsets[i] + (num_comp - 1) * comp_stride < l_size, ceed, CEED_ERROR_BACKEND,
7286574a04fSJeremy L Thompson                   "Restriction offset %" CeedInt_FMT " (%" CeedInt_FMT ") out of range [0, %" CeedInt_FMT "]", i, offsets[i], l_size);
7292b730f8bSJeremy L Thompson       }
7302b730f8bSJeremy L Thompson     }
7313661185eSjeremylt 
73292fe105eSJeremy L Thompson     // Copy data
733d1d35e2fSjeremylt     switch (copy_mode) {
73421617c04Sjeremylt       case CEED_COPY_VALUES:
7352b730f8bSJeremy L Thompson         CeedCallBackend(CeedMalloc(num_elem * elem_size, &impl->offsets_allocated));
7362b730f8bSJeremy L Thompson         memcpy(impl->offsets_allocated, offsets, num_elem * elem_size * sizeof(offsets[0]));
737d979a051Sjeremylt         impl->offsets = impl->offsets_allocated;
73821617c04Sjeremylt         break;
73921617c04Sjeremylt       case CEED_OWN_POINTER:
740d979a051Sjeremylt         impl->offsets_allocated = (CeedInt *)offsets;
741d979a051Sjeremylt         impl->offsets           = impl->offsets_allocated;
74221617c04Sjeremylt         break;
74321617c04Sjeremylt       case CEED_USE_POINTER:
744d979a051Sjeremylt         impl->offsets = offsets;
74521617c04Sjeremylt     }
746fcbe8c06SSebastian Grimberg 
747fcbe8c06SSebastian Grimberg     // Orientation data
748fcbe8c06SSebastian Grimberg     if (rstr_type == CEED_RESTRICTION_ORIENTED) {
7490305e208SSebastian Grimberg       CeedCheck(orients != NULL, ceed, CEED_ERROR_BACKEND, "No orients array provided for oriented restriction");
750fcbe8c06SSebastian Grimberg       switch (copy_mode) {
751fcbe8c06SSebastian Grimberg         case CEED_COPY_VALUES:
752fcbe8c06SSebastian Grimberg           CeedCallBackend(CeedMalloc(num_elem * elem_size, &impl->orients_allocated));
753fcbe8c06SSebastian Grimberg           memcpy(impl->orients_allocated, orients, num_elem * elem_size * sizeof(orients[0]));
754fcbe8c06SSebastian Grimberg           impl->orients = impl->orients_allocated;
755fcbe8c06SSebastian Grimberg           break;
756fcbe8c06SSebastian Grimberg         case CEED_OWN_POINTER:
757fcbe8c06SSebastian Grimberg           impl->orients_allocated = (bool *)orients;
758fcbe8c06SSebastian Grimberg           impl->orients           = impl->orients_allocated;
759fcbe8c06SSebastian Grimberg           break;
760fcbe8c06SSebastian Grimberg         case CEED_USE_POINTER:
761fcbe8c06SSebastian Grimberg           impl->orients = orients;
762fcbe8c06SSebastian Grimberg       }
763fcbe8c06SSebastian Grimberg     } else if (rstr_type == CEED_RESTRICTION_CURL_ORIENTED) {
7640305e208SSebastian Grimberg       CeedCheck(curl_orients != NULL, ceed, CEED_ERROR_BACKEND, "No curl_orients array provided for oriented restriction");
765fcbe8c06SSebastian Grimberg       switch (copy_mode) {
766fcbe8c06SSebastian Grimberg         case CEED_COPY_VALUES:
767fcbe8c06SSebastian Grimberg           CeedCallBackend(CeedMalloc(num_elem * 3 * elem_size, &impl->curl_orients_allocated));
768fcbe8c06SSebastian Grimberg           memcpy(impl->curl_orients_allocated, curl_orients, num_elem * 3 * elem_size * sizeof(curl_orients[0]));
769fcbe8c06SSebastian Grimberg           impl->curl_orients = impl->curl_orients_allocated;
770fcbe8c06SSebastian Grimberg           break;
771fcbe8c06SSebastian Grimberg         case CEED_OWN_POINTER:
7720c73c039SSebastian Grimberg           impl->curl_orients_allocated = (CeedInt8 *)curl_orients;
773fcbe8c06SSebastian Grimberg           impl->curl_orients           = impl->curl_orients_allocated;
774fcbe8c06SSebastian Grimberg           break;
775fcbe8c06SSebastian Grimberg         case CEED_USE_POINTER:
776fcbe8c06SSebastian Grimberg           impl->curl_orients = curl_orients;
777fcbe8c06SSebastian Grimberg       }
778fcbe8c06SSebastian Grimberg     }
77992fe105eSJeremy L Thompson   }
780fe2413ffSjeremylt 
7811cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionSetData(rstr, impl));
7821cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionSetELayout(rstr, layout));
7831cc2c60dSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", rstr, "Apply", CeedElemRestrictionApply_Ref));
784*2c7e7413SJeremy L Thompson   if (rstr_type == CEED_RESTRICTION_POINTS) {
785*2c7e7413SJeremy L Thompson     CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", rstr, "ApplyAtPoints", CeedElemRestrictionApplyAtPoints_Ref));
786*2c7e7413SJeremy L Thompson   } else {
7871cc2c60dSJeremy L Thompson     CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", rstr, "ApplyUnsigned", CeedElemRestrictionApplyUnsigned_Ref));
7881cc2c60dSJeremy L Thompson     CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", rstr, "ApplyUnoriented", CeedElemRestrictionApplyUnoriented_Ref));
7891cc2c60dSJeremy L Thompson     CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", rstr, "ApplyBlock", CeedElemRestrictionApplyBlock_Ref));
7901cc2c60dSJeremy L Thompson     CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", rstr, "GetOrientations", CeedElemRestrictionGetOrientations_Ref));
7911cc2c60dSJeremy L Thompson     CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", rstr, "GetCurlOrientations", CeedElemRestrictionGetCurlOrientations_Ref));
792*2c7e7413SJeremy L Thompson   }
793*2c7e7413SJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", rstr, "GetOffsets", CeedElemRestrictionGetOffsets_Ref));
7941cc2c60dSJeremy L Thompson   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", rstr, "Destroy", CeedElemRestrictionDestroy_Ref));
795d979a051Sjeremylt 
796ad70ee2cSJeremy L Thompson   // Set apply function based upon num_comp, block_size, and comp_stride
797ad70ee2cSJeremy L Thompson   CeedInt index = -1;
798ad70ee2cSJeremy L Thompson 
799ad70ee2cSJeremy L Thompson   if (block_size < 10) index = 100 * num_comp + 10 * block_size + (comp_stride == 1);
800ad70ee2cSJeremy L Thompson   switch (index) {
801d979a051Sjeremylt     case 110:
802d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_110;
803d979a051Sjeremylt       break;
804d979a051Sjeremylt     case 111:
805d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_111;
806d979a051Sjeremylt       break;
807d979a051Sjeremylt     case 180:
808d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_180;
809d979a051Sjeremylt       break;
810d979a051Sjeremylt     case 181:
811d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_181;
812d979a051Sjeremylt       break;
813d979a051Sjeremylt     case 310:
814d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_310;
815d979a051Sjeremylt       break;
816d979a051Sjeremylt     case 311:
817d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_311;
818d979a051Sjeremylt       break;
819d979a051Sjeremylt     case 380:
820d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_380;
821d979a051Sjeremylt       break;
822d979a051Sjeremylt     case 381:
823d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_381;
824d979a051Sjeremylt       break;
825bf4d1581Sjeremylt     // LCOV_EXCL_START
826d979a051Sjeremylt     case 510:
827d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_510;
828d979a051Sjeremylt       break;
829bf4d1581Sjeremylt     // LCOV_EXCL_STOP
830d979a051Sjeremylt     case 511:
831d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_511;
832d979a051Sjeremylt       break;
833bf4d1581Sjeremylt     // LCOV_EXCL_START
834d979a051Sjeremylt     case 580:
835d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_580;
836d979a051Sjeremylt       break;
837bf4d1581Sjeremylt     // LCOV_EXCL_STOP
838d979a051Sjeremylt     case 581:
839d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_581;
840d979a051Sjeremylt       break;
841d979a051Sjeremylt     default:
842d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_Core;
843d979a051Sjeremylt       break;
844d979a051Sjeremylt   }
845e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
84621617c04Sjeremylt }
847fc0567d9Srezgarshakeri 
848fc0567d9Srezgarshakeri //------------------------------------------------------------------------------
849