xref: /libCEED/rust/libceed-sys/c-src/backends/ref/ceed-ref-restriction.c (revision cf415216851e455690c5797385b9bba87c798dc1)
1d275d636SJeremy L Thompson // Copyright (c) 2017-2025, 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,
21171d97d0SJeremy L Thompson                                                                       CeedSize v_offset, const CeedScalar *__restrict__ uu,
22eda0adbcSSebastian Grimberg                                                                       CeedScalar *__restrict__ vv) {
2394648b7dSSebastian Grimberg   // No offsets provided, identity restriction
24d1d35e2fSjeremylt   bool has_backend_strides;
25ad70ee2cSJeremy L Thompson 
261cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionHasBackendStrides(rstr, &has_backend_strides));
27d1d35e2fSjeremylt   if (has_backend_strides) {
28d1d35e2fSjeremylt     // CPU backend strides are {1, elem_size, elem_size*num_comp}
297f90ec76Sjeremylt     // This if branch is left separate to allow better inlining
3033e3c889SJeremy L Thompson     for (CeedSize e = start * block_size; e < stop * block_size; e += block_size) {
3133e3c889SJeremy L Thompson       CeedPragmaSIMD for (CeedSize k = 0; k < num_comp; k++) {
3233e3c889SJeremy L Thompson         CeedPragmaSIMD for (CeedSize n = 0; n < elem_size; n++) {
3333e3c889SJeremy L Thompson           CeedPragmaSIMD for (CeedSize j = 0; j < block_size; j++) {
3433e3c889SJeremy L Thompson             vv[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] =
3533e3c889SJeremy L Thompson                 uu[n + k * elem_size + CeedIntMin(e + j, num_elem - 1) * elem_size * (CeedSize)num_comp];
362b730f8bSJeremy L Thompson           }
372b730f8bSJeremy L Thompson         }
382b730f8bSJeremy L Thompson       }
392b730f8bSJeremy L Thompson     }
407f90ec76Sjeremylt   } else {
417f90ec76Sjeremylt     // User provided strides
427f90ec76Sjeremylt     CeedInt strides[3];
43ad70ee2cSJeremy L Thompson 
4456c48462SJeremy L Thompson     CeedCallBackend(CeedElemRestrictionGetStrides(rstr, strides));
4533e3c889SJeremy L Thompson     for (CeedSize e = start * block_size; e < stop * block_size; e += block_size) {
4633e3c889SJeremy L Thompson       CeedPragmaSIMD for (CeedSize k = 0; k < num_comp; k++) {
4733e3c889SJeremy L Thompson         CeedPragmaSIMD for (CeedSize n = 0; n < elem_size; n++) {
4833e3c889SJeremy L Thompson           CeedPragmaSIMD for (CeedSize j = 0; j < block_size; j++) {
4933e3c889SJeremy L Thompson             vv[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] =
5033e3c889SJeremy L Thompson                 uu[n * strides[0] + k * strides[1] + CeedIntMin(e + j, num_elem - 1) * (CeedSize)strides[2]];
512b730f8bSJeremy L Thompson           }
522b730f8bSJeremy L Thompson         }
532b730f8bSJeremy L Thompson       }
542b730f8bSJeremy L Thompson     }
557509a596Sjeremylt   }
5694648b7dSSebastian Grimberg   return CEED_ERROR_SUCCESS;
5794648b7dSSebastian Grimberg }
5894648b7dSSebastian Grimberg 
59eda0adbcSSebastian Grimberg static inline int CeedElemRestrictionApplyOffsetNoTranspose_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size,
6094648b7dSSebastian Grimberg                                                                      const CeedInt comp_stride, CeedInt start, CeedInt stop, CeedInt num_elem,
61171d97d0SJeremy L Thompson                                                                      CeedInt elem_size, CeedSize v_offset, const CeedScalar *__restrict__ uu,
62eda0adbcSSebastian Grimberg                                                                      CeedScalar *__restrict__ vv) {
63fcbe8c06SSebastian Grimberg   // Default restriction with offsets
6494648b7dSSebastian Grimberg   CeedElemRestriction_Ref *impl;
65ad70ee2cSJeremy L Thompson 
661cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
6733e3c889SJeremy L Thompson   for (CeedSize e = start * block_size; e < stop * block_size; e += block_size) {
6833e3c889SJeremy L Thompson     CeedPragmaSIMD for (CeedSize k = 0; k < num_comp; k++) {
6933e3c889SJeremy L Thompson       CeedPragmaSIMD for (CeedSize i = 0; i < elem_size * block_size; i++) {
7033e3c889SJeremy L Thompson         vv[elem_size * (k * block_size + e * num_comp) + i - v_offset] = uu[impl->offsets[i + e * elem_size] + k * comp_stride];
71fcbe8c06SSebastian Grimberg       }
72fcbe8c06SSebastian Grimberg     }
73fcbe8c06SSebastian Grimberg   }
7494648b7dSSebastian Grimberg   return CEED_ERROR_SUCCESS;
7594648b7dSSebastian Grimberg }
7694648b7dSSebastian Grimberg 
771cc2c60dSJeremy L Thompson static inline int CeedElemRestrictionApplyOrientedNoTranspose_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size,
7894648b7dSSebastian Grimberg                                                                        const CeedInt comp_stride, CeedInt start, CeedInt stop, CeedInt num_elem,
79171d97d0SJeremy L Thompson                                                                        CeedInt elem_size, CeedSize v_offset, const CeedScalar *__restrict__ uu,
80eda0adbcSSebastian Grimberg                                                                        CeedScalar *__restrict__ vv) {
81fcbe8c06SSebastian Grimberg   // Restriction with orientations
8294648b7dSSebastian Grimberg   CeedElemRestriction_Ref *impl;
83ad70ee2cSJeremy L Thompson 
841cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
8533e3c889SJeremy L Thompson   for (CeedSize e = start * block_size; e < stop * block_size; e += block_size) {
8633e3c889SJeremy L Thompson     CeedPragmaSIMD for (CeedSize k = 0; k < num_comp; k++) {
8733e3c889SJeremy L Thompson       CeedPragmaSIMD for (CeedSize i = 0; i < elem_size * block_size; i++) {
8833e3c889SJeremy L Thompson         vv[elem_size * (k * block_size + e * num_comp) + i - v_offset] =
897c1dbaffSSebastian Grimberg             uu[impl->offsets[i + e * elem_size] + k * comp_stride] * (impl->orients[i + e * elem_size] ? -1.0 : 1.0);
90fcbe8c06SSebastian Grimberg       }
91fcbe8c06SSebastian Grimberg     }
92fcbe8c06SSebastian Grimberg   }
9394648b7dSSebastian Grimberg   return CEED_ERROR_SUCCESS;
9494648b7dSSebastian Grimberg }
9594648b7dSSebastian Grimberg 
961cc2c60dSJeremy L Thompson static inline int CeedElemRestrictionApplyCurlOrientedNoTranspose_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size,
9794648b7dSSebastian Grimberg                                                                            const CeedInt comp_stride, CeedInt start, CeedInt stop, CeedInt num_elem,
98171d97d0SJeremy L Thompson                                                                            CeedInt elem_size, CeedSize v_offset, const CeedScalar *__restrict__ uu,
99eda0adbcSSebastian Grimberg                                                                            CeedScalar *__restrict__ vv) {
10077d1c127SSebastian Grimberg   // Restriction with tridiagonal transformation
10194648b7dSSebastian Grimberg   CeedElemRestriction_Ref *impl;
102ad70ee2cSJeremy L Thompson 
1031cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
10433e3c889SJeremy L Thompson   for (CeedSize e = start * block_size; e < stop * block_size; e += block_size) {
10533e3c889SJeremy L Thompson     CeedPragmaSIMD for (CeedSize k = 0; k < num_comp; k++) {
10633e3c889SJeremy L Thompson       CeedSize n = 0;
1075c7e0f51SSebastian Grimberg 
10833e3c889SJeremy L Thompson       CeedPragmaSIMD for (CeedSize j = 0; j < block_size; j++) {
10933e3c889SJeremy L Thompson         vv[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] =
110ad70ee2cSJeremy L Thompson             uu[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] *
111ad70ee2cSJeremy L Thompson                 impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size] +
112ad70ee2cSJeremy L Thompson             uu[impl->offsets[j + (n + 1) * block_size + e * elem_size] + k * comp_stride] *
113ad70ee2cSJeremy L Thompson                 impl->curl_orients[j + (3 * n + 2) * block_size + e * 3 * elem_size];
1140c73c039SSebastian Grimberg       }
1155c7e0f51SSebastian Grimberg       CeedPragmaSIMD for (n = 1; n < elem_size - 1; n++) {
11633e3c889SJeremy L Thompson         CeedPragmaSIMD for (CeedSize j = 0; j < block_size; j++) {
11733e3c889SJeremy L Thompson           vv[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] =
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 + 0) * block_size + e * 3 * elem_size] +
120ad70ee2cSJeremy L Thompson               uu[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] *
121ad70ee2cSJeremy L Thompson                   impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size] +
122ad70ee2cSJeremy L Thompson               uu[impl->offsets[j + (n + 1) * block_size + e * elem_size] + k * comp_stride] *
123ad70ee2cSJeremy L Thompson                   impl->curl_orients[j + (3 * n + 2) * block_size + e * 3 * elem_size];
1240c73c039SSebastian Grimberg         }
1250c73c039SSebastian Grimberg       }
12633e3c889SJeremy L Thompson       CeedPragmaSIMD for (CeedSize j = 0; j < block_size; j++) {
12733e3c889SJeremy L Thompson         vv[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] =
128ad70ee2cSJeremy L Thompson             uu[impl->offsets[j + (n - 1) * block_size + e * elem_size] + k * comp_stride] *
129ad70ee2cSJeremy L Thompson                 impl->curl_orients[j + (3 * n + 0) * block_size + e * 3 * elem_size] +
130ad70ee2cSJeremy L Thompson             uu[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] *
131ad70ee2cSJeremy L Thompson                 impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size];
1322b730f8bSJeremy L Thompson       }
1332b730f8bSJeremy L Thompson     }
1342b730f8bSJeremy L Thompson   }
1350c73c039SSebastian Grimberg   return CEED_ERROR_SUCCESS;
136fcbe8c06SSebastian Grimberg }
1370c73c039SSebastian Grimberg 
1381cc2c60dSJeremy L Thompson static inline int CeedElemRestrictionApplyCurlOrientedUnsignedNoTranspose_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp,
139ad70ee2cSJeremy L Thompson                                                                                    const CeedInt block_size, const CeedInt comp_stride, CeedInt start,
14094648b7dSSebastian Grimberg                                                                                    CeedInt stop, CeedInt num_elem, CeedInt elem_size,
141171d97d0SJeremy L Thompson                                                                                    CeedSize v_offset, const CeedScalar *__restrict__ uu,
142eda0adbcSSebastian Grimberg                                                                                    CeedScalar *__restrict__ vv) {
14394648b7dSSebastian Grimberg   // Restriction with (unsigned) tridiagonal transformation
1440c73c039SSebastian Grimberg   CeedElemRestriction_Ref *impl;
145ad70ee2cSJeremy L Thompson 
1461cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
14733e3c889SJeremy L Thompson   for (CeedSize e = start * block_size; e < stop * block_size; e += block_size) {
14833e3c889SJeremy L Thompson     CeedPragmaSIMD for (CeedSize k = 0; k < num_comp; k++) {
14933e3c889SJeremy L Thompson       CeedSize n = 0;
150ad70ee2cSJeremy L Thompson 
15133e3c889SJeremy L Thompson       CeedPragmaSIMD for (CeedSize j = 0; j < block_size; j++) {
15233e3c889SJeremy L Thompson         vv[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] =
153ad70ee2cSJeremy L Thompson             uu[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] *
154ad70ee2cSJeremy L Thompson                 abs(impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size]) +
155ad70ee2cSJeremy L Thompson             uu[impl->offsets[j + (n + 1) * block_size + e * elem_size] + k * comp_stride] *
156ad70ee2cSJeremy L Thompson                 abs(impl->curl_orients[j + (3 * n + 2) * block_size + e * 3 * elem_size]);
1577c1dbaffSSebastian Grimberg       }
1585c7e0f51SSebastian Grimberg       CeedPragmaSIMD for (n = 1; n < elem_size - 1; n++) {
15933e3c889SJeremy L Thompson         CeedPragmaSIMD for (CeedSize j = 0; j < block_size; j++) {
16033e3c889SJeremy L Thompson           vv[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] =
161ad70ee2cSJeremy L Thompson               uu[impl->offsets[j + (n - 1) * block_size + e * elem_size] + k * comp_stride] *
162ad70ee2cSJeremy L Thompson                   abs(impl->curl_orients[j + (3 * n + 0) * block_size + e * 3 * elem_size]) +
163ad70ee2cSJeremy L Thompson               uu[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] *
164ad70ee2cSJeremy L Thompson                   abs(impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size]) +
165ad70ee2cSJeremy L Thompson               uu[impl->offsets[j + (n + 1) * block_size + e * elem_size] + k * comp_stride] *
166ad70ee2cSJeremy L Thompson                   abs(impl->curl_orients[j + (3 * n + 2) * block_size + e * 3 * elem_size]);
1677c1dbaffSSebastian Grimberg         }
1687c1dbaffSSebastian Grimberg       }
16933e3c889SJeremy L Thompson       CeedPragmaSIMD for (CeedSize j = 0; j < block_size; j++) {
17033e3c889SJeremy L Thompson         vv[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] =
171ad70ee2cSJeremy L Thompson             uu[impl->offsets[j + (n - 1) * block_size + e * elem_size] + k * comp_stride] *
172ad70ee2cSJeremy L Thompson                 abs(impl->curl_orients[j + (3 * n + 0) * block_size + e * 3 * elem_size]) +
173ad70ee2cSJeremy L Thompson             uu[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] *
174ad70ee2cSJeremy L Thompson                 abs(impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size]);
1757c1dbaffSSebastian Grimberg       }
1767c1dbaffSSebastian Grimberg     }
1777c1dbaffSSebastian Grimberg   }
1787c1dbaffSSebastian Grimberg   return CEED_ERROR_SUCCESS;
1797c1dbaffSSebastian Grimberg }
1807c1dbaffSSebastian Grimberg 
1811cc2c60dSJeremy L Thompson static inline int CeedElemRestrictionApplyStridedTranspose_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size,
18294648b7dSSebastian Grimberg                                                                     CeedInt start, CeedInt stop, CeedInt num_elem, CeedInt elem_size,
183171d97d0SJeremy L Thompson                                                                     CeedSize v_offset, const CeedScalar *__restrict__ uu,
184eda0adbcSSebastian Grimberg                                                                     CeedScalar *__restrict__ vv) {
18594648b7dSSebastian Grimberg   // No offsets provided, identity restriction
186d1d35e2fSjeremylt   bool has_backend_strides;
187ad70ee2cSJeremy L Thompson 
1881cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionHasBackendStrides(rstr, &has_backend_strides));
189d1d35e2fSjeremylt   if (has_backend_strides) {
190d1d35e2fSjeremylt     // CPU backend strides are {1, elem_size, elem_size*num_comp}
1917f90ec76Sjeremylt     // This if brach is left separate to allow better inlining
19233e3c889SJeremy L Thompson     for (CeedSize e = start * block_size; e < stop * block_size; e += block_size) {
19333e3c889SJeremy L Thompson       CeedPragmaSIMD for (CeedSize k = 0; k < num_comp; k++) {
19433e3c889SJeremy L Thompson         CeedPragmaSIMD for (CeedSize n = 0; n < elem_size; n++) {
19533e3c889SJeremy L Thompson           CeedPragmaSIMD for (CeedSize j = 0; j < CeedIntMin(block_size, num_elem - e); j++) {
19633e3c889SJeremy 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];
1972b730f8bSJeremy L Thompson           }
1982b730f8bSJeremy L Thompson         }
1992b730f8bSJeremy L Thompson       }
2002b730f8bSJeremy L Thompson     }
2017f90ec76Sjeremylt   } else {
2027f90ec76Sjeremylt     // User provided strides
2037f90ec76Sjeremylt     CeedInt strides[3];
204ad70ee2cSJeremy L Thompson 
20556c48462SJeremy L Thompson     CeedCallBackend(CeedElemRestrictionGetStrides(rstr, strides));
206ad70ee2cSJeremy L Thompson     for (CeedInt e = start * block_size; e < stop * block_size; e += block_size) {
20733e3c889SJeremy L Thompson       CeedPragmaSIMD for (CeedSize k = 0; k < num_comp; k++) {
20833e3c889SJeremy L Thompson         CeedPragmaSIMD for (CeedSize n = 0; n < elem_size; n++) {
20933e3c889SJeremy L Thompson           CeedPragmaSIMD for (CeedSize j = 0; j < CeedIntMin(block_size, num_elem - e); j++) {
21033e3c889SJeremy L Thompson             vv[n * strides[0] + k * strides[1] + (e + j) * strides[2]] +=
21133e3c889SJeremy L Thompson                 uu[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset];
2122b730f8bSJeremy L Thompson           }
2132b730f8bSJeremy L Thompson         }
2142b730f8bSJeremy L Thompson       }
2152b730f8bSJeremy L Thompson     }
216523b8ea0Sjeremylt   }
21794648b7dSSebastian Grimberg   return CEED_ERROR_SUCCESS;
21894648b7dSSebastian Grimberg }
21994648b7dSSebastian Grimberg 
220eda0adbcSSebastian Grimberg static inline int CeedElemRestrictionApplyOffsetTranspose_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size,
22194648b7dSSebastian Grimberg                                                                    const CeedInt comp_stride, CeedInt start, CeedInt stop, CeedInt num_elem,
222171d97d0SJeremy L Thompson                                                                    CeedInt elem_size, CeedSize v_offset, const CeedScalar *__restrict__ uu,
223eda0adbcSSebastian Grimberg                                                                    CeedScalar *__restrict__ vv) {
224fcbe8c06SSebastian Grimberg   // Default restriction with offsets
22594648b7dSSebastian Grimberg   CeedElemRestriction_Ref *impl;
226ad70ee2cSJeremy L Thompson 
2271cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
22833e3c889SJeremy L Thompson   for (CeedSize e = start * block_size; e < stop * block_size; e += block_size) {
22933e3c889SJeremy L Thompson     for (CeedSize k = 0; k < num_comp; k++) {
23033e3c889SJeremy L Thompson       for (CeedSize i = 0; i < elem_size * block_size; i += block_size) {
2318d94b059Sjeremylt         // Iteration bound set to discard padding elements
23233e3c889SJeremy L Thompson         for (CeedSize j = i; j < i + CeedIntMin(block_size, num_elem - e); j++) {
2335c7e0f51SSebastian Grimberg           CeedScalar vv_loc;
23458c07c4fSSebastian Grimberg 
23533e3c889SJeremy L Thompson           vv_loc = uu[elem_size * (k * block_size + e * num_comp) + j - v_offset];
2365c7e0f51SSebastian Grimberg           CeedPragmaAtomic vv[impl->offsets[j + e * elem_size] + k * comp_stride] += vv_loc;
237fcbe8c06SSebastian Grimberg         }
238fcbe8c06SSebastian Grimberg       }
239fcbe8c06SSebastian Grimberg     }
240fcbe8c06SSebastian Grimberg   }
24194648b7dSSebastian Grimberg   return CEED_ERROR_SUCCESS;
24294648b7dSSebastian Grimberg }
24394648b7dSSebastian Grimberg 
2441cc2c60dSJeremy L Thompson static inline int CeedElemRestrictionApplyOrientedTranspose_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size,
24594648b7dSSebastian Grimberg                                                                      const CeedInt comp_stride, CeedInt start, CeedInt stop, CeedInt num_elem,
246171d97d0SJeremy L Thompson                                                                      CeedInt elem_size, CeedSize v_offset, const CeedScalar *__restrict__ uu,
247eda0adbcSSebastian Grimberg                                                                      CeedScalar *__restrict__ vv) {
248fcbe8c06SSebastian Grimberg   // Restriction with orientations
24994648b7dSSebastian Grimberg   CeedElemRestriction_Ref *impl;
250ad70ee2cSJeremy L Thompson 
2511cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
25233e3c889SJeremy L Thompson   for (CeedSize e = start * block_size; e < stop * block_size; e += block_size) {
25333e3c889SJeremy L Thompson     for (CeedSize k = 0; k < num_comp; k++) {
25433e3c889SJeremy L Thompson       for (CeedSize i = 0; i < elem_size * block_size; i += block_size) {
255fcbe8c06SSebastian Grimberg         // Iteration bound set to discard padding elements
25633e3c889SJeremy L Thompson         for (CeedSize j = i; j < i + CeedIntMin(block_size, num_elem - e); j++) {
2575c7e0f51SSebastian Grimberg           CeedScalar vv_loc;
25858c07c4fSSebastian Grimberg 
25933e3c889SJeremy L Thompson           vv_loc = uu[elem_size * (k * block_size + e * num_comp) + j - v_offset] * (impl->orients[j + e * elem_size] ? -1.0 : 1.0);
2605c7e0f51SSebastian Grimberg           CeedPragmaAtomic vv[impl->offsets[j + e * elem_size] + k * comp_stride] += vv_loc;
261fcbe8c06SSebastian Grimberg         }
262fcbe8c06SSebastian Grimberg       }
263fcbe8c06SSebastian Grimberg     }
264fcbe8c06SSebastian Grimberg   }
26594648b7dSSebastian Grimberg   return CEED_ERROR_SUCCESS;
26694648b7dSSebastian Grimberg }
26794648b7dSSebastian Grimberg 
2681cc2c60dSJeremy L Thompson static inline int CeedElemRestrictionApplyCurlOrientedTranspose_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size,
26994648b7dSSebastian Grimberg                                                                          const CeedInt comp_stride, CeedInt start, CeedInt stop, CeedInt num_elem,
270171d97d0SJeremy L Thompson                                                                          CeedInt elem_size, CeedSize v_offset, const CeedScalar *__restrict__ uu,
271eda0adbcSSebastian Grimberg                                                                          CeedScalar *__restrict__ vv) {
27277d1c127SSebastian Grimberg   // Restriction with tridiagonal transformation
27394648b7dSSebastian Grimberg   CeedElemRestriction_Ref *impl;
2745c7e0f51SSebastian Grimberg   CeedScalar               vv_loc[block_size];
275ad70ee2cSJeremy L Thompson 
2761cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
27733e3c889SJeremy L Thompson   for (CeedSize e = start * block_size; e < stop * block_size; e += block_size) {
27833e3c889SJeremy L Thompson     for (CeedSize k = 0; k < num_comp; k++) {
279fcbe8c06SSebastian Grimberg       // Iteration bound set to discard padding elements
28033e3c889SJeremy L Thompson       const CeedSize block_end = CeedIntMin(block_size, num_elem - e);
28133e3c889SJeremy L Thompson       CeedSize       n         = 0;
28258c07c4fSSebastian Grimberg 
28333e3c889SJeremy L Thompson       CeedPragmaSIMD for (CeedSize j = 0; j < block_end; j++) {
28433e3c889SJeremy L Thompson         vv_loc[j] = uu[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] *
285ad70ee2cSJeremy L Thompson                         impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size] +
28633e3c889SJeremy 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 + 3) * block_size + e * 3 * elem_size];
2885c7e0f51SSebastian Grimberg       }
28933e3c889SJeremy L Thompson       for (CeedSize j = 0; j < block_end; j++) {
2905c7e0f51SSebastian Grimberg         CeedPragmaAtomic vv[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] += vv_loc[j];
2910c73c039SSebastian Grimberg       }
2920c73c039SSebastian Grimberg       for (n = 1; n < elem_size - 1; n++) {
2935c7e0f51SSebastian Grimberg         CeedPragmaSIMD for (CeedInt j = 0; j < block_end; j++) {
29433e3c889SJeremy L Thompson           vv_loc[j] = uu[e * elem_size * num_comp + (k * elem_size + n - 1) * block_size + j - v_offset] *
295ad70ee2cSJeremy L Thompson                           impl->curl_orients[j + (3 * n - 1) * block_size + e * 3 * elem_size] +
29633e3c889SJeremy L Thompson                       uu[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] *
297ad70ee2cSJeremy L Thompson                           impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size] +
29833e3c889SJeremy L Thompson                       uu[e * elem_size * num_comp + (k * elem_size + n + 1) * block_size + j - v_offset] *
299ad70ee2cSJeremy L Thompson                           impl->curl_orients[j + (3 * n + 3) * block_size + e * 3 * elem_size];
3000c73c039SSebastian Grimberg         }
30133e3c889SJeremy L Thompson         for (CeedSize j = 0; j < block_end; j++) {
3025c7e0f51SSebastian Grimberg           CeedPragmaAtomic vv[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] += vv_loc[j];
3035c7e0f51SSebastian Grimberg         }
3045c7e0f51SSebastian Grimberg       }
30533e3c889SJeremy L Thompson       CeedPragmaSIMD for (CeedSize j = 0; j < block_end; j++) {
30633e3c889SJeremy L Thompson         vv_loc[j] = uu[e * elem_size * num_comp + (k * elem_size + n - 1) * block_size + j - v_offset] *
307ad70ee2cSJeremy L Thompson                         impl->curl_orients[j + (3 * n - 1) * block_size + e * 3 * elem_size] +
30833e3c889SJeremy L Thompson                     uu[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] *
309ad70ee2cSJeremy L Thompson                         impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size];
3105c7e0f51SSebastian Grimberg       }
31133e3c889SJeremy L Thompson       for (CeedSize j = 0; j < block_end; j++) {
3125c7e0f51SSebastian Grimberg         CeedPragmaAtomic vv[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] += vv_loc[j];
31321617c04Sjeremylt       }
314b435c5a6Srezgarshakeri     }
3152b730f8bSJeremy L Thompson   }
316e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
31721617c04Sjeremylt }
31821617c04Sjeremylt 
3191cc2c60dSJeremy L Thompson static inline int CeedElemRestrictionApplyCurlOrientedUnsignedTranspose_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp,
320ad70ee2cSJeremy L Thompson                                                                                  const CeedInt block_size, const CeedInt comp_stride, CeedInt start,
321171d97d0SJeremy L Thompson                                                                                  CeedInt stop, CeedInt num_elem, CeedInt elem_size, CeedSize v_offset,
322eda0adbcSSebastian Grimberg                                                                                  const CeedScalar *__restrict__ uu, CeedScalar *__restrict__ vv) {
32394648b7dSSebastian Grimberg   // Restriction with (unsigned) tridiagonal transformation
3247c1dbaffSSebastian Grimberg   CeedElemRestriction_Ref *impl;
3255c7e0f51SSebastian Grimberg   CeedScalar               vv_loc[block_size];
326ad70ee2cSJeremy L Thompson 
3271cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
32833e3c889SJeremy L Thompson   for (CeedSize e = start * block_size; e < stop * block_size; e += block_size) {
32933e3c889SJeremy L Thompson     for (CeedSize k = 0; k < num_comp; k++) {
3307c1dbaffSSebastian Grimberg       // Iteration bound set to discard padding elements
33133e3c889SJeremy L Thompson       const CeedSize block_end = CeedIntMin(block_size, num_elem - e);
33233e3c889SJeremy L Thompson       CeedSize       n         = 0;
333ad70ee2cSJeremy L Thompson 
33433e3c889SJeremy L Thompson       CeedPragmaSIMD for (CeedSize j = 0; j < block_end; j++) {
33533e3c889SJeremy L Thompson         vv_loc[j] = uu[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] *
336ad70ee2cSJeremy L Thompson                         abs(impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size]) +
33733e3c889SJeremy L Thompson                     uu[e * elem_size * num_comp + (k * elem_size + n + 1) * block_size + j - v_offset] *
338ad70ee2cSJeremy L Thompson                         abs(impl->curl_orients[j + (3 * n + 3) * block_size + e * 3 * elem_size]);
3395c7e0f51SSebastian Grimberg       }
34033e3c889SJeremy L Thompson       for (CeedSize j = 0; j < block_end; j++) {
3415c7e0f51SSebastian Grimberg         CeedPragmaAtomic vv[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] += vv_loc[j];
3427c1dbaffSSebastian Grimberg       }
3437c1dbaffSSebastian Grimberg       for (n = 1; n < elem_size - 1; n++) {
34433e3c889SJeremy L Thompson         CeedPragmaSIMD for (CeedSize j = 0; j < block_end; j++) {
34533e3c889SJeremy L Thompson           vv_loc[j] = uu[e * elem_size * num_comp + (k * elem_size + n - 1) * block_size + j - v_offset] *
346ad70ee2cSJeremy L Thompson                           abs(impl->curl_orients[j + (3 * n - 1) * block_size + e * 3 * elem_size]) +
34733e3c889SJeremy L Thompson                       uu[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] *
348ad70ee2cSJeremy L Thompson                           abs(impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size]) +
34933e3c889SJeremy L Thompson                       uu[e * elem_size * num_comp + (k * elem_size + n + 1) * block_size + j - v_offset] *
350ad70ee2cSJeremy L Thompson                           abs(impl->curl_orients[j + (3 * n + 3) * block_size + e * 3 * elem_size]);
3517c1dbaffSSebastian Grimberg         }
35233e3c889SJeremy L Thompson         for (CeedSize j = 0; j < block_end; j++) {
3535c7e0f51SSebastian Grimberg           CeedPragmaAtomic vv[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] += vv_loc[j];
3545c7e0f51SSebastian Grimberg         }
3555c7e0f51SSebastian Grimberg       }
35633e3c889SJeremy L Thompson       CeedPragmaSIMD for (CeedSize j = 0; j < block_end; j++) {
35733e3c889SJeremy L Thompson         vv_loc[j] = uu[e * elem_size * num_comp + (k * elem_size + n - 1) * block_size + j - v_offset] *
358ad70ee2cSJeremy L Thompson                         abs(impl->curl_orients[j + (3 * n - 1) * block_size + e * 3 * elem_size]) +
35933e3c889SJeremy L Thompson                     uu[e * elem_size * num_comp + (k * elem_size + n) * block_size + j - v_offset] *
360ad70ee2cSJeremy L Thompson                         abs(impl->curl_orients[j + (3 * n + 1) * block_size + e * 3 * elem_size]);
3615c7e0f51SSebastian Grimberg       }
36233e3c889SJeremy L Thompson       for (CeedSize j = 0; j < block_end; j++) {
3635c7e0f51SSebastian Grimberg         CeedPragmaAtomic vv[impl->offsets[j + n * block_size + e * elem_size] + k * comp_stride] += vv_loc[j];
3647c1dbaffSSebastian Grimberg       }
3657c1dbaffSSebastian Grimberg     }
3667c1dbaffSSebastian Grimberg   }
3677c1dbaffSSebastian Grimberg   return CEED_ERROR_SUCCESS;
3687c1dbaffSSebastian Grimberg }
3697c1dbaffSSebastian Grimberg 
3701249ccc5SJeremy L Thompson static inline int CeedElemRestrictionApplyAtPointsInElement_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp, CeedInt start, CeedInt stop,
371eda0adbcSSebastian Grimberg                                                                      CeedTransposeMode t_mode, const CeedScalar *__restrict__ uu,
372eda0adbcSSebastian Grimberg                                                                      CeedScalar *__restrict__ vv) {
373171d97d0SJeremy L Thompson   CeedInt                  num_points, l_vec_offset;
374171d97d0SJeremy L Thompson   CeedSize                 e_vec_offset = 0;
37505fa913cSJeremy L Thompson   CeedElemRestriction_Ref *impl;
37605fa913cSJeremy L Thompson 
37705fa913cSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
37805fa913cSJeremy L Thompson   for (CeedInt e = start; e < stop; e++) {
3790930e4e7SJeremy L Thompson     l_vec_offset = impl->offsets[e];
38005fa913cSJeremy L Thompson     CeedCallBackend(CeedElemRestrictionGetNumPointsInElement(rstr, e, &num_points));
38105fa913cSJeremy L Thompson     if (t_mode == CEED_NOTRANSPOSE) {
38233e3c889SJeremy L Thompson       for (CeedSize i = 0; i < num_points; i++) {
38333e3c889SJeremy L Thompson         for (CeedSize j = 0; j < num_comp; j++) vv[j * num_points + i + e_vec_offset] = uu[impl->offsets[i + l_vec_offset] * num_comp + j];
38405fa913cSJeremy L Thompson       }
38505fa913cSJeremy L Thompson     } else {
38633e3c889SJeremy L Thompson       for (CeedSize i = 0; i < num_points; i++) {
3870b63de31SJeremy L Thompson         for (CeedSize j = 0; j < num_comp; j++) vv[impl->offsets[i + l_vec_offset] * num_comp + j] += uu[j * num_points + i + e_vec_offset];
38805fa913cSJeremy L Thompson       }
38905fa913cSJeremy L Thompson     }
390171d97d0SJeremy L Thompson     e_vec_offset += num_points * (CeedSize)num_comp;
39105fa913cSJeremy L Thompson   }
39205fa913cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
39305fa913cSJeremy L Thompson }
39405fa913cSJeremy L Thompson 
3951cc2c60dSJeremy L Thompson static inline int CeedElemRestrictionApply_Ref_Core(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size,
396ad70ee2cSJeremy L Thompson                                                     const CeedInt comp_stride, CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs,
397ad70ee2cSJeremy L Thompson                                                     bool use_orients, CeedVector u, CeedVector v, CeedRequest *request) {
398171d97d0SJeremy L Thompson   CeedInt             num_elem, elem_size;
399171d97d0SJeremy L Thompson   CeedSize            v_offset = 0;
400ad70ee2cSJeremy L Thompson   CeedRestrictionType rstr_type;
4017c1dbaffSSebastian Grimberg   const CeedScalar   *uu;
4027c1dbaffSSebastian Grimberg   CeedScalar         *vv;
403ad70ee2cSJeremy L Thompson 
4041cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumElements(rstr, &num_elem));
4051cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetElementSize(rstr, &elem_size));
406171d97d0SJeremy L Thompson   v_offset = start * block_size * elem_size * (CeedSize)num_comp;
4071cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetType(rstr, &rstr_type));
40894648b7dSSebastian Grimberg   CeedCallBackend(CeedVectorGetArrayRead(u, CEED_MEM_HOST, &uu));
409ad70ee2cSJeremy L Thompson 
41094648b7dSSebastian Grimberg   if (t_mode == CEED_TRANSPOSE) {
41194648b7dSSebastian Grimberg     // Sum into for transpose mode, E-vector to L-vector
41294648b7dSSebastian Grimberg     CeedCallBackend(CeedVectorGetArray(v, CEED_MEM_HOST, &vv));
41394648b7dSSebastian Grimberg   } else {
41494648b7dSSebastian Grimberg     // Overwrite for notranspose mode, L-vector to E-vector
41594648b7dSSebastian Grimberg     CeedCallBackend(CeedVectorGetArrayWrite(v, CEED_MEM_HOST, &vv));
41694648b7dSSebastian Grimberg   }
41794648b7dSSebastian Grimberg   if (t_mode == CEED_TRANSPOSE) {
4187c1dbaffSSebastian Grimberg     // Restriction from E-vector to L-vector
4197c1dbaffSSebastian Grimberg     // Performing v += r^T * u
4207c1dbaffSSebastian Grimberg     // uu has shape [elem_size, num_comp, num_elem], row-major
4217c1dbaffSSebastian Grimberg     // vv has shape [nnodes, num_comp]
4227c1dbaffSSebastian Grimberg     // Sum into for transpose mode
4237c1dbaffSSebastian Grimberg     switch (rstr_type) {
4247c1dbaffSSebastian Grimberg       case CEED_RESTRICTION_STRIDED:
4255d10938bSJeremy L Thompson         CeedCallBackend(
4261cc2c60dSJeremy L Thompson             CeedElemRestrictionApplyStridedTranspose_Ref_Core(rstr, num_comp, block_size, start, stop, num_elem, elem_size, v_offset, uu, vv));
42794648b7dSSebastian Grimberg         break;
42861a27d74SSebastian Grimberg       case CEED_RESTRICTION_STANDARD:
429eda0adbcSSebastian Grimberg         CeedCallBackend(CeedElemRestrictionApplyOffsetTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop, num_elem, elem_size,
4305d10938bSJeremy L Thompson                                                                          v_offset, uu, vv));
43194648b7dSSebastian Grimberg         break;
4327c1dbaffSSebastian Grimberg       case CEED_RESTRICTION_ORIENTED:
43394648b7dSSebastian Grimberg         if (use_signs) {
4341cc2c60dSJeremy L Thompson           CeedCallBackend(CeedElemRestrictionApplyOrientedTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop, num_elem,
4351cc2c60dSJeremy L Thompson                                                                              elem_size, v_offset, uu, vv));
43694648b7dSSebastian Grimberg         } else {
437eda0adbcSSebastian Grimberg           CeedCallBackend(CeedElemRestrictionApplyOffsetTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop, num_elem, elem_size,
438eda0adbcSSebastian Grimberg                                                                            v_offset, uu, vv));
43994648b7dSSebastian Grimberg         }
44094648b7dSSebastian Grimberg         break;
44194648b7dSSebastian Grimberg       case CEED_RESTRICTION_CURL_ORIENTED:
44294648b7dSSebastian Grimberg         if (use_signs && use_orients) {
4431cc2c60dSJeremy L Thompson           CeedCallBackend(CeedElemRestrictionApplyCurlOrientedTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop, num_elem,
4445d10938bSJeremy L Thompson                                                                                  elem_size, v_offset, uu, vv));
44594648b7dSSebastian Grimberg         } else if (use_orients) {
4461cc2c60dSJeremy L Thompson           CeedCallBackend(CeedElemRestrictionApplyCurlOrientedUnsignedTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop,
4471cc2c60dSJeremy L Thompson                                                                                          num_elem, elem_size, v_offset, uu, vv));
44894648b7dSSebastian Grimberg         } else {
449eda0adbcSSebastian Grimberg           CeedCallBackend(CeedElemRestrictionApplyOffsetTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop, num_elem, elem_size,
450eda0adbcSSebastian Grimberg                                                                            v_offset, uu, vv));
45194648b7dSSebastian Grimberg         }
45294648b7dSSebastian Grimberg         break;
4532c7e7413SJeremy L Thompson       case CEED_RESTRICTION_POINTS:
4541249ccc5SJeremy L Thompson         CeedCallBackend(CeedElemRestrictionApplyAtPointsInElement_Ref_Core(rstr, num_comp, start, stop, t_mode, uu, vv));
4552c7e7413SJeremy L Thompson         break;
45694648b7dSSebastian Grimberg     }
45794648b7dSSebastian Grimberg   } else {
45894648b7dSSebastian Grimberg     // Restriction from L-vector to E-vector
45994648b7dSSebastian Grimberg     // Perform: v = r * u
46094648b7dSSebastian Grimberg     // vv has shape [elem_size, num_comp, num_elem], row-major
46194648b7dSSebastian Grimberg     // uu has shape [nnodes, num_comp]
46294648b7dSSebastian Grimberg     // Overwrite for notranspose mode
46394648b7dSSebastian Grimberg     switch (rstr_type) {
46494648b7dSSebastian Grimberg       case CEED_RESTRICTION_STRIDED:
4655d10938bSJeremy L Thompson         CeedCallBackend(
4661cc2c60dSJeremy L Thompson             CeedElemRestrictionApplyStridedNoTranspose_Ref_Core(rstr, num_comp, block_size, start, stop, num_elem, elem_size, v_offset, uu, vv));
46794648b7dSSebastian Grimberg         break;
46861a27d74SSebastian Grimberg       case CEED_RESTRICTION_STANDARD:
469eda0adbcSSebastian Grimberg         CeedCallBackend(CeedElemRestrictionApplyOffsetNoTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop, num_elem, elem_size,
470eda0adbcSSebastian Grimberg                                                                            v_offset, uu, vv));
47194648b7dSSebastian Grimberg         break;
47294648b7dSSebastian Grimberg       case CEED_RESTRICTION_ORIENTED:
47394648b7dSSebastian Grimberg         if (use_signs) {
4741cc2c60dSJeremy L Thompson           CeedCallBackend(CeedElemRestrictionApplyOrientedNoTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop, num_elem,
4751cc2c60dSJeremy L Thompson                                                                                elem_size, v_offset, uu, vv));
47694648b7dSSebastian Grimberg         } else {
477eda0adbcSSebastian Grimberg           CeedCallBackend(CeedElemRestrictionApplyOffsetNoTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop, num_elem,
4781cc2c60dSJeremy L Thompson                                                                              elem_size, v_offset, uu, vv));
47994648b7dSSebastian Grimberg         }
48094648b7dSSebastian Grimberg         break;
48194648b7dSSebastian Grimberg       case CEED_RESTRICTION_CURL_ORIENTED:
48294648b7dSSebastian Grimberg         if (use_signs && use_orients) {
4831cc2c60dSJeremy L Thompson           CeedCallBackend(CeedElemRestrictionApplyCurlOrientedNoTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop, num_elem,
4845d10938bSJeremy L Thompson                                                                                    elem_size, v_offset, uu, vv));
48594648b7dSSebastian Grimberg         } else if (use_orients) {
4861cc2c60dSJeremy L Thompson           CeedCallBackend(CeedElemRestrictionApplyCurlOrientedUnsignedNoTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop,
4875d10938bSJeremy L Thompson                                                                                            num_elem, elem_size, v_offset, uu, vv));
48894648b7dSSebastian Grimberg         } else {
489eda0adbcSSebastian Grimberg           CeedCallBackend(CeedElemRestrictionApplyOffsetNoTranspose_Ref_Core(rstr, num_comp, block_size, comp_stride, start, stop, num_elem,
4901cc2c60dSJeremy L Thompson                                                                              elem_size, v_offset, uu, vv));
49194648b7dSSebastian Grimberg         }
49294648b7dSSebastian Grimberg         break;
4932c7e7413SJeremy L Thompson       case CEED_RESTRICTION_POINTS:
4941249ccc5SJeremy L Thompson         CeedCallBackend(CeedElemRestrictionApplyAtPointsInElement_Ref_Core(rstr, num_comp, start, stop, t_mode, uu, vv));
4952c7e7413SJeremy L Thompson         break;
49694648b7dSSebastian Grimberg     }
4977c1dbaffSSebastian Grimberg   }
4987c1dbaffSSebastian Grimberg   CeedCallBackend(CeedVectorRestoreArrayRead(u, &uu));
4997c1dbaffSSebastian Grimberg   CeedCallBackend(CeedVectorRestoreArray(v, &vv));
5007c1dbaffSSebastian Grimberg   if (request != CEED_REQUEST_IMMEDIATE && request != CEED_REQUEST_ORDERED) *request = NULL;
5017c1dbaffSSebastian Grimberg   return CEED_ERROR_SUCCESS;
5027c1dbaffSSebastian Grimberg }
5037c1dbaffSSebastian Grimberg 
5047c1dbaffSSebastian Grimberg //------------------------------------------------------------------------------
505f10650afSjeremylt // ElemRestriction Apply - Common Sizes
506f10650afSjeremylt //------------------------------------------------------------------------------
5071cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_110(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, 1, 1, comp_stride, start, stop, t_mode, use_signs, use_orients, u, v, request);
511d979a051Sjeremylt }
512d979a051Sjeremylt 
5131cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_111(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
5147c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
5157c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
5161cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 1, 1, 1, start, stop, t_mode, use_signs, use_orients, u, v, request);
5174d2a38eeSjeremylt }
5184d2a38eeSjeremylt 
5191cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_180(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
5207c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
5217c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
5221cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 1, 8, comp_stride, start, stop, t_mode, use_signs, use_orients, u, v, request);
5239c36149bSjeremylt }
5249c36149bSjeremylt 
5251cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_181(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
5267c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
5277c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
5281cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 1, 8, 1, start, stop, t_mode, use_signs, use_orients, u, v, request);
5299c36149bSjeremylt }
5309c36149bSjeremylt 
5311cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_310(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
5327c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
5337c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
5341cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 3, 1, comp_stride, start, stop, t_mode, use_signs, use_orients, u, v, request);
535d979a051Sjeremylt }
536d979a051Sjeremylt 
5371cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_311(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
5387c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
5397c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
5401cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 3, 1, 1, start, stop, t_mode, use_signs, use_orients, u, v, request);
541d979a051Sjeremylt }
542d979a051Sjeremylt 
5431cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_380(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
5447c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
5457c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
5461cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 3, 8, comp_stride, start, stop, t_mode, use_signs, use_orients, u, v, request);
547d979a051Sjeremylt }
548d979a051Sjeremylt 
5491cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_381(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
5507c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
5517c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
5521cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 3, 8, 1, start, stop, t_mode, use_signs, use_orients, u, v, request);
553d979a051Sjeremylt }
554d979a051Sjeremylt 
555bf4d1581Sjeremylt // LCOV_EXCL_START
556*cf415216SJeremy L Thompson static int CeedElemRestrictionApply_Ref_410(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
557*cf415216SJeremy L Thompson                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
558*cf415216SJeremy L Thompson                                             CeedVector v, CeedRequest *request) {
559*cf415216SJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 4, 1, comp_stride, start, stop, t_mode, use_signs, use_orients, u, v, request);
560*cf415216SJeremy L Thompson }
561*cf415216SJeremy L Thompson 
562*cf415216SJeremy L Thompson static int CeedElemRestrictionApply_Ref_411(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
563*cf415216SJeremy L Thompson                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
564*cf415216SJeremy L Thompson                                             CeedVector v, CeedRequest *request) {
565*cf415216SJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 4, 1, 1, start, stop, t_mode, use_signs, use_orients, u, v, request);
566*cf415216SJeremy L Thompson }
567*cf415216SJeremy L Thompson 
568*cf415216SJeremy L Thompson static int CeedElemRestrictionApply_Ref_480(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
569*cf415216SJeremy L Thompson                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
570*cf415216SJeremy L Thompson                                             CeedVector v, CeedRequest *request) {
571*cf415216SJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 4, 8, comp_stride, start, stop, t_mode, use_signs, use_orients, u, v, request);
572*cf415216SJeremy L Thompson }
573*cf415216SJeremy L Thompson 
574*cf415216SJeremy L Thompson static int CeedElemRestrictionApply_Ref_481(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
575*cf415216SJeremy L Thompson                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
576*cf415216SJeremy L Thompson                                             CeedVector v, CeedRequest *request) {
577*cf415216SJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 4, 8, 1, start, stop, t_mode, use_signs, use_orients, u, v, request);
578*cf415216SJeremy L Thompson }
579*cf415216SJeremy L Thompson 
5801cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_510(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
5817c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
5827c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
5831cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 5, 1, comp_stride, start, stop, t_mode, use_signs, use_orients, u, v, request);
584d979a051Sjeremylt }
585bf4d1581Sjeremylt // LCOV_EXCL_STOP
586d979a051Sjeremylt 
5871cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_511(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
5887c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
5897c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
5901cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 5, 1, 1, start, stop, t_mode, use_signs, use_orients, u, v, request);
591d979a051Sjeremylt }
592d979a051Sjeremylt 
593bf4d1581Sjeremylt // LCOV_EXCL_START
5941cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_580(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
5957c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
5967c1dbaffSSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
5971cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 5, 8, comp_stride, start, stop, t_mode, use_signs, use_orients, u, v, request);
598d979a051Sjeremylt }
599bf4d1581Sjeremylt // LCOV_EXCL_STOP
600d979a051Sjeremylt 
6011cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref_581(CeedElemRestriction rstr, const CeedInt num_comp, const CeedInt block_size, const CeedInt comp_stride,
6027c1dbaffSSebastian Grimberg                                             CeedInt start, CeedInt stop, CeedTransposeMode t_mode, bool use_signs, bool use_orients, CeedVector u,
6030c73c039SSebastian Grimberg                                             CeedVector v, CeedRequest *request) {
6041cc2c60dSJeremy L Thompson   return CeedElemRestrictionApply_Ref_Core(rstr, 5, 8, 1, start, stop, t_mode, use_signs, use_orients, u, v, request);
6054d2a38eeSjeremylt }
6064d2a38eeSjeremylt 
607f10650afSjeremylt //------------------------------------------------------------------------------
608f10650afSjeremylt // ElemRestriction Apply
609f10650afSjeremylt //------------------------------------------------------------------------------
6101cc2c60dSJeremy L Thompson static int CeedElemRestrictionApply_Ref(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector v, CeedRequest *request) {
611ad70ee2cSJeremy L Thompson   CeedInt                  num_block, block_size, num_comp, comp_stride;
612ad70ee2cSJeremy L Thompson   CeedElemRestriction_Ref *impl;
613ad70ee2cSJeremy L Thompson 
6141cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumBlocks(rstr, &num_block));
6151cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetBlockSize(rstr, &block_size));
6161cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
6171cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCompStride(rstr, &comp_stride));
6181cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
6191cc2c60dSJeremy L Thompson   CeedCallBackend(impl->Apply(rstr, num_comp, block_size, comp_stride, 0, num_block, t_mode, true, true, u, v, request));
6205d10938bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
621f30b1135SSebastian Grimberg }
622f30b1135SSebastian Grimberg 
623f30b1135SSebastian Grimberg //------------------------------------------------------------------------------
624f30b1135SSebastian Grimberg // ElemRestriction Apply Unsigned
625f30b1135SSebastian Grimberg //------------------------------------------------------------------------------
6261cc2c60dSJeremy L Thompson static int CeedElemRestrictionApplyUnsigned_Ref(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
6271cc2c60dSJeremy L Thompson                                                 CeedRequest *request) {
628ad70ee2cSJeremy L Thompson   CeedInt                  num_block, block_size, num_comp, comp_stride;
629ad70ee2cSJeremy L Thompson   CeedElemRestriction_Ref *impl;
630ad70ee2cSJeremy L Thompson 
6311cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumBlocks(rstr, &num_block));
6321cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetBlockSize(rstr, &block_size));
6331cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
6341cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCompStride(rstr, &comp_stride));
6351cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
6361cc2c60dSJeremy L Thompson   CeedCallBackend(impl->Apply(rstr, num_comp, block_size, comp_stride, 0, num_block, t_mode, false, true, u, v, request));
6375d10938bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
6387c1dbaffSSebastian Grimberg }
6397c1dbaffSSebastian Grimberg 
6407c1dbaffSSebastian Grimberg //------------------------------------------------------------------------------
6417c1dbaffSSebastian Grimberg // ElemRestriction Apply Unoriented
6427c1dbaffSSebastian Grimberg //------------------------------------------------------------------------------
6431cc2c60dSJeremy L Thompson static int CeedElemRestrictionApplyUnoriented_Ref(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
6441cc2c60dSJeremy L Thompson                                                   CeedRequest *request) {
645ad70ee2cSJeremy L Thompson   CeedInt                  num_block, block_size, num_comp, comp_stride;
646ad70ee2cSJeremy L Thompson   CeedElemRestriction_Ref *impl;
647ad70ee2cSJeremy L Thompson 
6481cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumBlocks(rstr, &num_block));
6491cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetBlockSize(rstr, &block_size));
6501cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
6511cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCompStride(rstr, &comp_stride));
6521cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
6531cc2c60dSJeremy L Thompson   CeedCallBackend(impl->Apply(rstr, num_comp, block_size, comp_stride, 0, num_block, t_mode, false, false, u, v, request));
6545d10938bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
6559c36149bSjeremylt }
656be9261b7Sjeremylt 
657f10650afSjeremylt //------------------------------------------------------------------------------
6582c7e7413SJeremy L Thompson // ElemRestriction Apply Points
6592c7e7413SJeremy L Thompson //------------------------------------------------------------------------------
660eda0adbcSSebastian Grimberg static int CeedElemRestrictionApplyAtPointsInElement_Ref(CeedElemRestriction rstr, CeedInt elem, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
6612c7e7413SJeremy L Thompson                                                          CeedRequest *request) {
66205fa913cSJeremy L Thompson   CeedInt                  num_comp;
6632c7e7413SJeremy L Thompson   CeedElemRestriction_Ref *impl;
6642c7e7413SJeremy L Thompson 
665eda0adbcSSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
666eda0adbcSSebastian Grimberg   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
667eda0adbcSSebastian Grimberg   return impl->Apply(rstr, num_comp, 0, 1, elem, elem + 1, t_mode, false, false, u, v, request);
6682c7e7413SJeremy L Thompson }
6692c7e7413SJeremy L Thompson 
6702c7e7413SJeremy L Thompson //------------------------------------------------------------------------------
671f10650afSjeremylt // ElemRestriction Apply Block
672f10650afSjeremylt //------------------------------------------------------------------------------
6731cc2c60dSJeremy L Thompson static int CeedElemRestrictionApplyBlock_Ref(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector v,
674074cb416Sjeremylt                                              CeedRequest *request) {
675ad70ee2cSJeremy L Thompson   CeedInt                  block_size, num_comp, comp_stride;
676ad70ee2cSJeremy L Thompson   CeedElemRestriction_Ref *impl;
677ad70ee2cSJeremy L Thompson 
6781cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetBlockSize(rstr, &block_size));
6791cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
6801cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCompStride(rstr, &comp_stride));
6811cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
6821cc2c60dSJeremy L Thompson   CeedCallBackend(impl->Apply(rstr, num_comp, block_size, comp_stride, block, block + 1, t_mode, true, true, u, v, request));
6835d10938bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
6849c36149bSjeremylt }
685be9261b7Sjeremylt 
686f10650afSjeremylt //------------------------------------------------------------------------------
687bd33150aSjeremylt // ElemRestriction Get Offsets
688bd33150aSjeremylt //------------------------------------------------------------------------------
6892b730f8bSJeremy L Thompson static int CeedElemRestrictionGetOffsets_Ref(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) {
690ad70ee2cSJeremy L Thompson   CeedElemRestriction_Ref *impl;
691ad70ee2cSJeremy L Thompson 
692ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
693bd33150aSjeremylt 
6946e536b99SJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_BACKEND, "Can only provide to HOST memory");
695bd33150aSjeremylt 
696bd33150aSjeremylt   *offsets = impl->offsets;
697e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
698bd33150aSjeremylt }
699bd33150aSjeremylt 
700bd33150aSjeremylt //------------------------------------------------------------------------------
70177d1c127SSebastian Grimberg // ElemRestriction Get Orientations
70277d1c127SSebastian Grimberg //------------------------------------------------------------------------------
70377d1c127SSebastian Grimberg static int CeedElemRestrictionGetOrientations_Ref(CeedElemRestriction rstr, CeedMemType mem_type, const bool **orients) {
704ad70ee2cSJeremy L Thompson   CeedElemRestriction_Ref *impl;
705ad70ee2cSJeremy L Thompson 
706ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
70777d1c127SSebastian Grimberg 
7086e536b99SJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_BACKEND, "Can only provide to HOST memory");
70977d1c127SSebastian Grimberg 
71077d1c127SSebastian Grimberg   *orients = impl->orients;
71177d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
71277d1c127SSebastian Grimberg }
71377d1c127SSebastian Grimberg 
71477d1c127SSebastian Grimberg //------------------------------------------------------------------------------
71577d1c127SSebastian Grimberg // ElemRestriction Get Curl-Conforming Orientations
71677d1c127SSebastian Grimberg //------------------------------------------------------------------------------
7170c73c039SSebastian Grimberg static int CeedElemRestrictionGetCurlOrientations_Ref(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt8 **curl_orients) {
718ad70ee2cSJeremy L Thompson   CeedElemRestriction_Ref *impl;
719ad70ee2cSJeremy L Thompson 
720ad70ee2cSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
72177d1c127SSebastian Grimberg 
7226e536b99SJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_BACKEND, "Can only provide to HOST memory");
72377d1c127SSebastian Grimberg 
72477d1c127SSebastian Grimberg   *curl_orients = impl->curl_orients;
72577d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
72677d1c127SSebastian Grimberg }
72777d1c127SSebastian Grimberg 
72877d1c127SSebastian Grimberg //------------------------------------------------------------------------------
729f10650afSjeremylt // ElemRestriction Destroy
730f10650afSjeremylt //------------------------------------------------------------------------------
7311cc2c60dSJeremy L Thompson static int CeedElemRestrictionDestroy_Ref(CeedElemRestriction rstr) {
732fe2413ffSjeremylt   CeedElemRestriction_Ref *impl;
73321617c04Sjeremylt 
7341cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetData(rstr, &impl));
735a267acd1SJeremy L Thompson   CeedCallBackend(CeedFree(&impl->offsets_owned));
736a267acd1SJeremy L Thompson   CeedCallBackend(CeedFree(&impl->orients_owned));
737a267acd1SJeremy L Thompson   CeedCallBackend(CeedFree(&impl->curl_orients_owned));
7382b730f8bSJeremy L Thompson   CeedCallBackend(CeedFree(&impl));
739e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
74021617c04Sjeremylt }
74121617c04Sjeremylt 
742f10650afSjeremylt //------------------------------------------------------------------------------
743f10650afSjeremylt // ElemRestriction Create
744f10650afSjeremylt //------------------------------------------------------------------------------
745fcbe8c06SSebastian Grimberg int CeedElemRestrictionCreate_Ref(CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orients,
7461cc2c60dSJeremy L Thompson                                   const CeedInt8 *curl_orients, CeedElemRestriction rstr) {
747ad70ee2cSJeremy L Thompson   Ceed                     ceed;
74807d5dec1SJeremy L Thompson   CeedInt                  num_elem, elem_size, num_block, block_size, num_comp, comp_stride, num_points = 0, num_offsets;
749ad70ee2cSJeremy L Thompson   CeedRestrictionType      rstr_type;
75021617c04Sjeremylt   CeedElemRestriction_Ref *impl;
751ad70ee2cSJeremy L Thompson 
7521cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCeed(rstr, &ceed));
7531cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumElements(rstr, &num_elem));
7541cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetElementSize(rstr, &elem_size));
7551cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumBlocks(rstr, &num_block));
7561cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetBlockSize(rstr, &block_size));
7571cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
7581cc2c60dSJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetCompStride(rstr, &comp_stride));
75922eb1385SJeremy L Thompson   CeedCallBackend(CeedElemRestrictionGetType(rstr, &rstr_type));
76021617c04Sjeremylt 
7616574a04fSJeremy L Thompson   CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Only MemType = HOST supported");
762dce49693SSebastian Grimberg 
7632b730f8bSJeremy L Thompson   CeedCallBackend(CeedCalloc(1, &impl));
764dce49693SSebastian Grimberg   CeedCallBackend(CeedElemRestrictionSetData(rstr, impl));
76522eb1385SJeremy L Thompson 
76622eb1385SJeremy L Thompson   // Set layouts
76722eb1385SJeremy L Thompson   {
76822eb1385SJeremy L Thompson     bool    has_backend_strides;
76922eb1385SJeremy L Thompson     CeedInt layout[3] = {1, elem_size, elem_size * num_comp};
77022eb1385SJeremy L Thompson 
771dce49693SSebastian Grimberg     CeedCallBackend(CeedElemRestrictionSetELayout(rstr, layout));
77222eb1385SJeremy L Thompson     if (rstr_type == CEED_RESTRICTION_STRIDED) {
77322eb1385SJeremy L Thompson       CeedCallBackend(CeedElemRestrictionHasBackendStrides(rstr, &has_backend_strides));
77422eb1385SJeremy L Thompson       if (has_backend_strides) {
77522eb1385SJeremy L Thompson         CeedCallBackend(CeedElemRestrictionSetLLayout(rstr, layout));
77622eb1385SJeremy L Thompson       }
77722eb1385SJeremy L Thompson     }
77822eb1385SJeremy L Thompson   }
7793661185eSjeremylt 
780ff1bc20eSJeremy L Thompson   // Expand E-vector size for AtPoints
781ff1bc20eSJeremy L Thompson   if (rstr_type == CEED_RESTRICTION_POINTS) {
782ff1bc20eSJeremy L Thompson     CeedSize max_points = 0, num_points_total = 0;
783ff1bc20eSJeremy L Thompson 
784ff1bc20eSJeremy L Thompson     for (CeedInt i = 0; i < num_elem; i++) {
785ff1bc20eSJeremy L Thompson       CeedInt num_points = offsets[i + 1] - offsets[i];
786ff1bc20eSJeremy L Thompson 
787ff1bc20eSJeremy L Thompson       max_points = CeedIntMax(max_points, num_points);
788ff1bc20eSJeremy L Thompson       num_points_total += num_points;
789ff1bc20eSJeremy L Thompson     }
790ff1bc20eSJeremy L Thompson     // -- Increase size for last element
791ff1bc20eSJeremy L Thompson     num_points_total += (max_points - (offsets[num_elem] - offsets[num_elem - 1]));
792ff1bc20eSJeremy L Thompson     CeedCallBackend(CeedElemRestrictionSetAtPointsEVectorSize(rstr, num_points_total * num_comp));
793ff1bc20eSJeremy L Thompson   }
794ff1bc20eSJeremy L Thompson 
79592fe105eSJeremy L Thompson   // Offsets data
796fcbe8c06SSebastian Grimberg   if (rstr_type != CEED_RESTRICTION_STRIDED) {
7973661185eSjeremylt     const char *resource;
798ad70ee2cSJeremy L Thompson 
799ad70ee2cSJeremy L Thompson     // Check indices for ref or memcheck backends
80035aed383SJeremy L Thompson     {
8019bc66399SJeremy L Thompson       Ceed current = ceed, ceed_parent = NULL;
80235aed383SJeremy L Thompson 
8039bc66399SJeremy L Thompson       CeedCallBackend(CeedGetParent(current, &ceed_parent));
8049bc66399SJeremy L Thompson       CeedCallBackend(CeedGetResource(ceed_parent, &resource));
8059bc66399SJeremy L Thompson       CeedCallBackend(CeedDestroy(&ceed_parent));
80635aed383SJeremy L Thompson     }
8071ba74105SJeremy L Thompson     if (!strcmp(resource, "/cpu/self/ref/serial") || !strcmp(resource, "/cpu/self/ref/blocked")) {
808e79b91d9SJeremy L Thompson       CeedSize l_size;
8093661185eSjeremylt 
8101cc2c60dSJeremy L Thompson       CeedCallBackend(CeedElemRestrictionGetLVectorSize(rstr, &l_size));
8112b730f8bSJeremy L Thompson       for (CeedInt i = 0; i < num_elem * elem_size; i++) {
8126574a04fSJeremy L Thompson         CeedCheck(offsets[i] >= 0 && offsets[i] + (num_comp - 1) * comp_stride < l_size, ceed, CEED_ERROR_BACKEND,
8136574a04fSJeremy L Thompson                   "Restriction offset %" CeedInt_FMT " (%" CeedInt_FMT ") out of range [0, %" CeedInt_FMT "]", i, offsets[i], l_size);
8142b730f8bSJeremy L Thompson       }
8152b730f8bSJeremy L Thompson     }
8163661185eSjeremylt 
81792fe105eSJeremy L Thompson     // Copy data
81807d5dec1SJeremy L Thompson     if (rstr_type == CEED_RESTRICTION_POINTS) CeedCallBackend(CeedElemRestrictionGetNumPoints(rstr, &num_points));
81907d5dec1SJeremy L Thompson     num_offsets = rstr_type == CEED_RESTRICTION_POINTS ? (num_elem + 1 + num_points) : (num_elem * elem_size);
820f5d1e504SJeremy L Thompson     CeedCallBackend(CeedSetHostCeedIntArray(offsets, copy_mode, num_offsets, &impl->offsets_owned, &impl->offsets_borrowed, &impl->offsets));
821fcbe8c06SSebastian Grimberg 
822fcbe8c06SSebastian Grimberg     // Orientation data
823fcbe8c06SSebastian Grimberg     if (rstr_type == CEED_RESTRICTION_ORIENTED) {
8240305e208SSebastian Grimberg       CeedCheck(orients != NULL, ceed, CEED_ERROR_BACKEND, "No orients array provided for oriented restriction");
825f5d1e504SJeremy L Thompson       CeedCallBackend(CeedSetHostBoolArray(orients, copy_mode, num_offsets, &impl->orients_owned, &impl->orients_borrowed, &impl->orients));
826fcbe8c06SSebastian Grimberg     } else if (rstr_type == CEED_RESTRICTION_CURL_ORIENTED) {
8270305e208SSebastian Grimberg       CeedCheck(curl_orients != NULL, ceed, CEED_ERROR_BACKEND, "No curl_orients array provided for oriented restriction");
828f5d1e504SJeremy L Thompson       CeedCallBackend(CeedSetHostCeedInt8Array(curl_orients, copy_mode, 3 * num_offsets, &impl->curl_orients_owned, &impl->curl_orients_borrowed,
829f5d1e504SJeremy L Thompson                                                &impl->curl_orients));
830fcbe8c06SSebastian Grimberg     }
83192fe105eSJeremy L Thompson   }
832fe2413ffSjeremylt 
833ad70ee2cSJeremy L Thompson   // Set apply function based upon num_comp, block_size, and comp_stride
834ad70ee2cSJeremy L Thompson   CeedInt index = -1;
835ad70ee2cSJeremy L Thompson 
836ad70ee2cSJeremy L Thompson   if (block_size < 10) index = 100 * num_comp + 10 * block_size + (comp_stride == 1);
837ad70ee2cSJeremy L Thompson   switch (index) {
838d979a051Sjeremylt     case 110:
839d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_110;
840d979a051Sjeremylt       break;
841d979a051Sjeremylt     case 111:
842d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_111;
843d979a051Sjeremylt       break;
844d979a051Sjeremylt     case 180:
845d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_180;
846d979a051Sjeremylt       break;
847d979a051Sjeremylt     case 181:
848d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_181;
849d979a051Sjeremylt       break;
850d979a051Sjeremylt     case 310:
851d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_310;
852d979a051Sjeremylt       break;
853d979a051Sjeremylt     case 311:
854d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_311;
855d979a051Sjeremylt       break;
856d979a051Sjeremylt     case 380:
857d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_380;
858d979a051Sjeremylt       break;
859d979a051Sjeremylt     case 381:
860d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_381;
861d979a051Sjeremylt       break;
862bf4d1581Sjeremylt     // LCOV_EXCL_START
863*cf415216SJeremy L Thompson     case 410:
864*cf415216SJeremy L Thompson       impl->Apply = CeedElemRestrictionApply_Ref_410;
865*cf415216SJeremy L Thompson       break;
866*cf415216SJeremy L Thompson     case 411:
867*cf415216SJeremy L Thompson       impl->Apply = CeedElemRestrictionApply_Ref_411;
868*cf415216SJeremy L Thompson       break;
869*cf415216SJeremy L Thompson     case 480:
870*cf415216SJeremy L Thompson       impl->Apply = CeedElemRestrictionApply_Ref_480;
871*cf415216SJeremy L Thompson       break;
872*cf415216SJeremy L Thompson     case 481:
873*cf415216SJeremy L Thompson       impl->Apply = CeedElemRestrictionApply_Ref_481;
874*cf415216SJeremy L Thompson       break;
875d979a051Sjeremylt     case 510:
876d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_510;
877d979a051Sjeremylt       break;
878bf4d1581Sjeremylt     // LCOV_EXCL_STOP
879d979a051Sjeremylt     case 511:
880d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_511;
881d979a051Sjeremylt       break;
882bf4d1581Sjeremylt     // LCOV_EXCL_START
883d979a051Sjeremylt     case 580:
884d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_580;
885d979a051Sjeremylt       break;
886bf4d1581Sjeremylt     // LCOV_EXCL_STOP
887d979a051Sjeremylt     case 581:
888d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_581;
889d979a051Sjeremylt       break;
890d979a051Sjeremylt     default:
891d979a051Sjeremylt       impl->Apply = CeedElemRestrictionApply_Ref_Core;
892d979a051Sjeremylt       break;
893d979a051Sjeremylt   }
894dce49693SSebastian Grimberg 
895dce49693SSebastian Grimberg   // Register backend functions
896dce49693SSebastian Grimberg   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", rstr, "Apply", CeedElemRestrictionApply_Ref));
897dce49693SSebastian Grimberg   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", rstr, "ApplyUnsigned", CeedElemRestrictionApplyUnsigned_Ref));
898dce49693SSebastian Grimberg   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", rstr, "ApplyUnoriented", CeedElemRestrictionApplyUnoriented_Ref));
899dce49693SSebastian Grimberg   if (rstr_type == CEED_RESTRICTION_POINTS) {
900dce49693SSebastian Grimberg     CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", rstr, "ApplyAtPointsInElement", CeedElemRestrictionApplyAtPointsInElement_Ref));
901dce49693SSebastian Grimberg   }
902dce49693SSebastian Grimberg   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", rstr, "ApplyBlock", CeedElemRestrictionApplyBlock_Ref));
903dce49693SSebastian Grimberg   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", rstr, "GetOffsets", CeedElemRestrictionGetOffsets_Ref));
904dce49693SSebastian Grimberg   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", rstr, "GetOrientations", CeedElemRestrictionGetOrientations_Ref));
905dce49693SSebastian Grimberg   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", rstr, "GetCurlOrientations", CeedElemRestrictionGetCurlOrientations_Ref));
906dce49693SSebastian Grimberg   CeedCallBackend(CeedSetBackendFunction(ceed, "ElemRestriction", rstr, "Destroy", CeedElemRestrictionDestroy_Ref));
9079bc66399SJeremy L Thompson   CeedCallBackend(CeedDestroy(&ceed));
908e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
90921617c04Sjeremylt }
910fc0567d9Srezgarshakeri 
911fc0567d9Srezgarshakeri //------------------------------------------------------------------------------
912