xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-elemrestriction.c (revision 196058356ce16dc55f8605a42694186898beb49b)
15aed82e4SJeremy L Thompson // Copyright (c) 2017-2024, 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.
3d7b241e6Sjeremylt //
43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
5d7b241e6Sjeremylt //
63d8e8822SJeremy L Thompson // This file is part of CEED:  http://github.com/ceed
7d7b241e6Sjeremylt 
83d576824SJeremy L Thompson #include <ceed-impl.h>
949aac155SJeremy L Thompson #include <ceed.h>
102b730f8bSJeremy L Thompson #include <ceed/backend.h>
113d576824SJeremy L Thompson #include <stdbool.h>
123d576824SJeremy L Thompson #include <stdio.h>
13c17ec2beSJeremy L Thompson #include <string.h>
14d7b241e6Sjeremylt 
157a982d89SJeremy L. Thompson /// @file
167a982d89SJeremy L. Thompson /// Implementation of CeedElemRestriction interfaces
177a982d89SJeremy L. Thompson 
187a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
197a982d89SJeremy L. Thompson /// CeedElemRestriction Library Internal Functions
207a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
217a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionDeveloper
227a982d89SJeremy L. Thompson /// @{
237a982d89SJeremy L. Thompson 
247a982d89SJeremy L. Thompson /**
25ca94c3ddSJeremy L Thompson   @brief Permute and pad offsets for a blocked `CeedElemRestriction`
267a982d89SJeremy L. Thompson 
27ca94c3ddSJeremy L Thompson   @param[in]  offsets       Array of shape `[num_elem, elem_size]`
28ca94c3ddSJeremy L Thompson   @param[out] block_offsets Array of permuted and padded array values of shape `[num_block, elem_size, block_size]`
29e7f679fcSJeremy L Thompson   @param[in]  num_block     Number of blocks
30ea61e9acSJeremy L Thompson   @param[in]  num_elem      Number of elements
31e7f679fcSJeremy L Thompson   @param[in]  block_size    Number of elements in a block
32ea61e9acSJeremy L Thompson   @param[in]  elem_size     Size of each element
337a982d89SJeremy L. Thompson 
347a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
357a982d89SJeremy L. Thompson 
367a982d89SJeremy L. Thompson   @ref Utility
377a982d89SJeremy L. Thompson **/
38e7f679fcSJeremy L Thompson int CeedPermutePadOffsets(const CeedInt *offsets, CeedInt *block_offsets, CeedInt num_block, CeedInt num_elem, CeedInt block_size,
39e7f679fcSJeremy L Thompson                           CeedInt elem_size) {
40e7f679fcSJeremy L Thompson   for (CeedInt e = 0; e < num_block * block_size; e += block_size) {
41e7f679fcSJeremy L Thompson     for (CeedInt j = 0; j < block_size; j++) {
422b730f8bSJeremy L Thompson       for (CeedInt k = 0; k < elem_size; k++) {
43e7f679fcSJeremy L Thompson         block_offsets[e * elem_size + k * block_size + j] = offsets[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
442b730f8bSJeremy L Thompson       }
452b730f8bSJeremy L Thompson     }
462b730f8bSJeremy L Thompson   }
47e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
487a982d89SJeremy L. Thompson }
497a982d89SJeremy L. Thompson 
5077d1c127SSebastian Grimberg /**
51ca94c3ddSJeremy L Thompson   @brief Permute and pad orientations for a blocked `CeedElemRestriction`
5277d1c127SSebastian Grimberg 
53ca94c3ddSJeremy L Thompson   @param[in]  orients       Array of shape `[num_elem, elem_size]`
54ca94c3ddSJeremy L Thompson   @param[out] block_orients Array of permuted and padded array values of shape `[num_block, elem_size, block_size]`
55e7f679fcSJeremy L Thompson   @param[in]  num_block     Number of blocks
5677d1c127SSebastian Grimberg   @param[in]  num_elem      Number of elements
57e7f679fcSJeremy L Thompson   @param[in]  block_size    Number of elements in a block
5877d1c127SSebastian Grimberg   @param[in]  elem_size     Size of each element
5977d1c127SSebastian Grimberg 
6077d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
6177d1c127SSebastian Grimberg 
6277d1c127SSebastian Grimberg   @ref Utility
6377d1c127SSebastian Grimberg **/
64e7f679fcSJeremy L Thompson int CeedPermutePadOrients(const bool *orients, bool *block_orients, CeedInt num_block, CeedInt num_elem, CeedInt block_size, CeedInt elem_size) {
65e7f679fcSJeremy L Thompson   for (CeedInt e = 0; e < num_block * block_size; e += block_size) {
66e7f679fcSJeremy L Thompson     for (CeedInt j = 0; j < block_size; j++) {
6777d1c127SSebastian Grimberg       for (CeedInt k = 0; k < elem_size; k++) {
68e7f679fcSJeremy L Thompson         block_orients[e * elem_size + k * block_size + j] = orients[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
6977d1c127SSebastian Grimberg       }
7077d1c127SSebastian Grimberg     }
7177d1c127SSebastian Grimberg   }
7277d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
7377d1c127SSebastian Grimberg }
7477d1c127SSebastian Grimberg 
750c73c039SSebastian Grimberg /**
76ca94c3ddSJeremy L Thompson   @brief Permute and pad curl-conforming orientations for a blocked `CeedElemRestriction`
770c73c039SSebastian Grimberg 
785c7e0f51SSebastian Grimberg   @param[in]  curl_orients       Array of shape `[num_elem, elem_size]`
79ca94c3ddSJeremy L Thompson   @param[out] block_curl_orients Array of permuted and padded array values of shape `[num_block, elem_size, block_size]`
80e7f679fcSJeremy L Thompson   @param[in]  num_block          Number of blocks
810c73c039SSebastian Grimberg   @param[in]  num_elem           Number of elements
82e7f679fcSJeremy L Thompson   @param[in]  block_size         Number of elements in a block
830c73c039SSebastian Grimberg   @param[in]  elem_size          Size of each element
840c73c039SSebastian Grimberg 
850c73c039SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
860c73c039SSebastian Grimberg 
870c73c039SSebastian Grimberg   @ref Utility
880c73c039SSebastian Grimberg **/
89e7f679fcSJeremy L Thompson int CeedPermutePadCurlOrients(const CeedInt8 *curl_orients, CeedInt8 *block_curl_orients, CeedInt num_block, CeedInt num_elem, CeedInt block_size,
900c73c039SSebastian Grimberg                               CeedInt elem_size) {
91e7f679fcSJeremy L Thompson   for (CeedInt e = 0; e < num_block * block_size; e += block_size) {
92e7f679fcSJeremy L Thompson     for (CeedInt j = 0; j < block_size; j++) {
930c73c039SSebastian Grimberg       for (CeedInt k = 0; k < elem_size; k++) {
94e7f679fcSJeremy L Thompson         block_curl_orients[e * elem_size + k * block_size + j] = curl_orients[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
950c73c039SSebastian Grimberg       }
960c73c039SSebastian Grimberg     }
970c73c039SSebastian Grimberg   }
980c73c039SSebastian Grimberg   return CEED_ERROR_SUCCESS;
990c73c039SSebastian Grimberg }
1000c73c039SSebastian Grimberg 
1017a982d89SJeremy L. Thompson /// @}
1027a982d89SJeremy L. Thompson 
1037a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1047a982d89SJeremy L. Thompson /// CeedElemRestriction Backend API
1057a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1067a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionBackend
1077a982d89SJeremy L. Thompson /// @{
1087a982d89SJeremy L. Thompson 
1097a982d89SJeremy L. Thompson /**
110ca94c3ddSJeremy L Thompson   @brief Get the type of a `CeedElemRestriction`
111a681ae63Sjeremylt 
112ca94c3ddSJeremy L Thompson   @param[in]  rstr      `CeedElemRestriction`
113fcbe8c06SSebastian Grimberg   @param[out] rstr_type Variable to store restriction type
114fcbe8c06SSebastian Grimberg 
115fcbe8c06SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
116fcbe8c06SSebastian Grimberg 
117fcbe8c06SSebastian Grimberg   @ref Backend
118fcbe8c06SSebastian Grimberg **/
119fcbe8c06SSebastian Grimberg int CeedElemRestrictionGetType(CeedElemRestriction rstr, CeedRestrictionType *rstr_type) {
120fcbe8c06SSebastian Grimberg   *rstr_type = rstr->rstr_type;
121fcbe8c06SSebastian Grimberg   return CEED_ERROR_SUCCESS;
122fcbe8c06SSebastian Grimberg }
123fcbe8c06SSebastian Grimberg 
124fcbe8c06SSebastian Grimberg /**
125ca94c3ddSJeremy L Thompson   @brief Get the strided status of a `CeedElemRestriction`
126fcbe8c06SSebastian Grimberg 
127ca94c3ddSJeremy L Thompson   @param[in]  rstr       `CeedElemRestriction`
128ca94c3ddSJeremy L Thompson   @param[out] is_strided Variable to store strided status
129ca94c3ddSJeremy L Thompson 
130ca94c3ddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
131ca94c3ddSJeremy L Thompson 
132ca94c3ddSJeremy L Thompson   @ref Backend
133fcbe8c06SSebastian Grimberg **/
134fcbe8c06SSebastian Grimberg int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) {
135fcbe8c06SSebastian Grimberg   *is_strided = (rstr->rstr_type == CEED_RESTRICTION_STRIDED);
136fcbe8c06SSebastian Grimberg   return CEED_ERROR_SUCCESS;
137fcbe8c06SSebastian Grimberg }
138fcbe8c06SSebastian Grimberg 
139fcbe8c06SSebastian Grimberg /**
140ca94c3ddSJeremy L Thompson   @brief Get the points status of a `CeedElemRestriction`
1413ac8f562SJeremy L Thompson 
142ca94c3ddSJeremy L Thompson   @param[in]  rstr      `CeedElemRestriction`
143ca94c3ddSJeremy L Thompson   @param[out] is_points Variable to store points status
144ca94c3ddSJeremy L Thompson 
145ca94c3ddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
146ca94c3ddSJeremy L Thompson 
147ca94c3ddSJeremy L Thompson   @ref Backend
1483ac8f562SJeremy L Thompson **/
1493ac8f562SJeremy L Thompson int CeedElemRestrictionIsPoints(CeedElemRestriction rstr, bool *is_points) {
1503ac8f562SJeremy L Thompson   *is_points = (rstr->rstr_type == CEED_RESTRICTION_POINTS);
1513ac8f562SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1523ac8f562SJeremy L Thompson }
1533ac8f562SJeremy L Thompson 
1543ac8f562SJeremy L Thompson /**
155ca94c3ddSJeremy L Thompson   @brief Check if two `CeedElemRestriction` created with @ref CeedElemRestrictionCreateAtPoints() and use the same points per element
15648acf710SJeremy L Thompson 
157ca94c3ddSJeremy L Thompson   @param[in]  rstr_a         First `CeedElemRestriction`
158ca94c3ddSJeremy L Thompson   @param[in]  rstr_b         Second `CeedElemRestriction`
15948acf710SJeremy L Thompson   @param[out] are_compatible Variable to store compatibility status
160ca94c3ddSJeremy L Thompson 
161ca94c3ddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
162ca94c3ddSJeremy L Thompson 
163ca94c3ddSJeremy L Thompson   @ref Backend
16448acf710SJeremy L Thompson **/
16548acf710SJeremy L Thompson int CeedElemRestrictionAtPointsAreCompatible(CeedElemRestriction rstr_a, CeedElemRestriction rstr_b, bool *are_compatible) {
16648acf710SJeremy L Thompson   CeedInt num_elem_a, num_elem_b, num_points_a, num_points_b;
1671203703bSJeremy L Thompson   Ceed    ceed;
1681203703bSJeremy L Thompson 
1691203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr_a, &ceed));
17048acf710SJeremy L Thompson 
17148acf710SJeremy L Thompson   // Cannot compare non-points restrictions
1721203703bSJeremy L Thompson   CeedCheck(rstr_a->rstr_type == CEED_RESTRICTION_POINTS, ceed, CEED_ERROR_UNSUPPORTED, "First CeedElemRestriction must be AtPoints");
1731203703bSJeremy L Thompson   CeedCheck(rstr_b->rstr_type == CEED_RESTRICTION_POINTS, ceed, CEED_ERROR_UNSUPPORTED, "Second CeedElemRestriction must be AtPoints");
17448acf710SJeremy L Thompson 
17548acf710SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr_a, &num_elem_a));
17648acf710SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr_b, &num_elem_b));
17748acf710SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumPoints(rstr_a, &num_points_a));
17848acf710SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumPoints(rstr_b, &num_points_b));
17948acf710SJeremy L Thompson 
18048acf710SJeremy L Thompson   // Check size and contents of offsets arrays
18148acf710SJeremy L Thompson   *are_compatible = true;
18248acf710SJeremy L Thompson   if (num_elem_a != num_elem_b) *are_compatible = false;
18348acf710SJeremy L Thompson   if (num_points_a != num_points_b) *are_compatible = false;
18448acf710SJeremy L Thompson   if (*are_compatible) {
18548acf710SJeremy L Thompson     const CeedInt *offsets_a, *offsets_b;
18648acf710SJeremy L Thompson 
18748acf710SJeremy L Thompson     CeedCall(CeedElemRestrictionGetOffsets(rstr_a, CEED_MEM_HOST, &offsets_a));
18848acf710SJeremy L Thompson     CeedCall(CeedElemRestrictionGetOffsets(rstr_b, CEED_MEM_HOST, &offsets_b));
18948acf710SJeremy L Thompson     for (CeedInt i = 0; i < num_elem_a + 1 + num_points_a; i++) *are_compatible &= offsets_a[i] == offsets_b[i];
19048acf710SJeremy L Thompson     CeedCall(CeedElemRestrictionRestoreOffsets(rstr_a, &offsets_a));
19148acf710SJeremy L Thompson     CeedCall(CeedElemRestrictionRestoreOffsets(rstr_b, &offsets_b));
19248acf710SJeremy L Thompson   }
19348acf710SJeremy L Thompson   return CEED_ERROR_SUCCESS;
19448acf710SJeremy L Thompson }
19548acf710SJeremy L Thompson 
19648acf710SJeremy L Thompson /**
197ca94c3ddSJeremy L Thompson   @brief Get the strides of a strided `CeedElemRestriction`
1987a982d89SJeremy L. Thompson 
199ca94c3ddSJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
200a681ae63Sjeremylt   @param[out] strides Variable to store strides array
2017a982d89SJeremy L. Thompson 
2027a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2037a982d89SJeremy L. Thompson 
2047a982d89SJeremy L. Thompson   @ref Backend
2057a982d89SJeremy L. Thompson **/
20656c48462SJeremy L Thompson int CeedElemRestrictionGetStrides(CeedElemRestriction rstr, CeedInt strides[3]) {
2076e536b99SJeremy L Thompson   CeedCheck(rstr->strides, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, "CeedElemRestriction has no stride data");
20856c48462SJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) strides[i] = rstr->strides[i];
209e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2107a982d89SJeremy L. Thompson }
2117a982d89SJeremy L. Thompson 
2127a982d89SJeremy L. Thompson /**
213ca94c3ddSJeremy L Thompson   @brief Get the backend stride status of a `CeedElemRestriction`
21477d1c127SSebastian Grimberg 
215ca94c3ddSJeremy L Thompson   @param[in]  rstr                 `CeedElemRestriction`
21677d1c127SSebastian Grimberg   @param[out] has_backend_strides  Variable to store stride status
21777d1c127SSebastian Grimberg 
21877d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
21977d1c127SSebastian Grimberg 
22077d1c127SSebastian Grimberg   @ref Backend
22177d1c127SSebastian Grimberg **/
22277d1c127SSebastian Grimberg int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, bool *has_backend_strides) {
2236e536b99SJeremy L Thompson   CeedCheck(rstr->strides, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, "CeedElemRestriction has no stride data");
22477d1c127SSebastian Grimberg   *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
22577d1c127SSebastian Grimberg                           (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
22677d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
22777d1c127SSebastian Grimberg }
22877d1c127SSebastian Grimberg 
22977d1c127SSebastian Grimberg /**
230ca94c3ddSJeremy L Thompson   @brief Get read-only access to a `CeedElemRestriction` offsets array by @ref CeedMemType
231bd33150aSjeremylt 
232ca94c3ddSJeremy L Thompson   @param[in]  rstr     `CeedElemRestriction` to retrieve offsets
233fcbe8c06SSebastian Grimberg   @param[in]  mem_type Memory type on which to access the array.
234fcbe8c06SSebastian Grimberg                          If the backend uses a different memory type, this will perform a copy (possibly cached).
235ca94c3ddSJeremy L Thompson   @param[out] offsets  Array on memory type `mem_type`
236bd33150aSjeremylt 
237bd33150aSjeremylt   @return An error code: 0 - success, otherwise - failure
238bd33150aSjeremylt 
239bd33150aSjeremylt   @ref User
240bd33150aSjeremylt **/
2412b730f8bSJeremy L Thompson int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) {
2427c1dbaffSSebastian Grimberg   if (rstr->rstr_base) {
2437c1dbaffSSebastian Grimberg     CeedCall(CeedElemRestrictionGetOffsets(rstr->rstr_base, mem_type, offsets));
244c17ec2beSJeremy L Thompson   } else {
2456e536b99SJeremy L Thompson     CeedCheck(rstr->GetOffsets, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED,
2466e536b99SJeremy L Thompson               "Backend does not support CeedElemRestrictionGetOffsets");
2472b730f8bSJeremy L Thompson     CeedCall(rstr->GetOffsets(rstr, mem_type, offsets));
248d1d35e2fSjeremylt     rstr->num_readers++;
249c17ec2beSJeremy L Thompson   }
250e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
251430758c8SJeremy L Thompson }
252430758c8SJeremy L Thompson 
253430758c8SJeremy L Thompson /**
254ca94c3ddSJeremy L Thompson   @brief Restore an offsets array obtained using @ref CeedElemRestrictionGetOffsets()
255430758c8SJeremy L Thompson 
256ca94c3ddSJeremy L Thompson   @param[in] rstr    `CeedElemRestriction` to restore
257ea61e9acSJeremy L Thompson   @param[in] offsets Array of offset data
258430758c8SJeremy L Thompson 
259430758c8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
260430758c8SJeremy L Thompson 
261430758c8SJeremy L Thompson   @ref User
262430758c8SJeremy L Thompson **/
2632b730f8bSJeremy L Thompson int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr, const CeedInt **offsets) {
2647c1dbaffSSebastian Grimberg   if (rstr->rstr_base) {
2657c1dbaffSSebastian Grimberg     CeedCall(CeedElemRestrictionRestoreOffsets(rstr->rstr_base, offsets));
266c17ec2beSJeremy L Thompson   } else {
267430758c8SJeremy L Thompson     *offsets = NULL;
268d1d35e2fSjeremylt     rstr->num_readers--;
269c17ec2beSJeremy L Thompson   }
270e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
271bd33150aSjeremylt }
272bd33150aSjeremylt 
273bd33150aSjeremylt /**
274ca94c3ddSJeremy L Thompson   @brief Get read-only access to a `CeedElemRestriction` orientations array by @ref CeedMemType
2753ac43b2cSJeremy L Thompson 
276ca94c3ddSJeremy L Thompson   @param[in]  rstr     `CeedElemRestriction` to retrieve orientations
277fcbe8c06SSebastian Grimberg   @param[in]  mem_type Memory type on which to access the array.
278fcbe8c06SSebastian Grimberg                          If the backend uses a different memory type, this will perform a copy (possibly cached).
279ca94c3ddSJeremy L Thompson   @param[out] orients  Array on memory type `mem_type`
2803ac43b2cSJeremy L Thompson 
2813ac43b2cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2823ac43b2cSJeremy L Thompson 
28377d1c127SSebastian Grimberg   @ref User
2843ac43b2cSJeremy L Thompson **/
28577d1c127SSebastian Grimberg int CeedElemRestrictionGetOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const bool **orients) {
2866e536b99SJeremy L Thompson   CeedCheck(rstr->GetOrientations, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED,
2876e536b99SJeremy L Thompson             "Backend does not support CeedElemRestrictionGetOrientations");
28877d1c127SSebastian Grimberg   CeedCall(rstr->GetOrientations(rstr, mem_type, orients));
28977d1c127SSebastian Grimberg   rstr->num_readers++;
290e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2913ac43b2cSJeremy L Thompson }
2923ac43b2cSJeremy L Thompson 
2933ac43b2cSJeremy L Thompson /**
294ca94c3ddSJeremy L Thompson   @brief Restore an orientations array obtained using @ref CeedElemRestrictionGetOrientations()
295b435c5a6Srezgarshakeri 
296ca94c3ddSJeremy L Thompson   @param[in] rstr    `CeedElemRestriction` to restore
29777d1c127SSebastian Grimberg   @param[in] orients Array of orientation data
298b435c5a6Srezgarshakeri 
299b435c5a6Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
300b435c5a6Srezgarshakeri 
30177d1c127SSebastian Grimberg   @ref User
302b435c5a6Srezgarshakeri **/
30377d1c127SSebastian Grimberg int CeedElemRestrictionRestoreOrientations(CeedElemRestriction rstr, const bool **orients) {
30477d1c127SSebastian Grimberg   *orients = NULL;
30577d1c127SSebastian Grimberg   rstr->num_readers--;
306b435c5a6Srezgarshakeri   return CEED_ERROR_SUCCESS;
307b435c5a6Srezgarshakeri }
308b435c5a6Srezgarshakeri 
309b435c5a6Srezgarshakeri /**
310ca94c3ddSJeremy L Thompson   @brief Get read-only access to a `CeedElemRestriction` curl-conforming orientations array by @ref CeedMemType
3117a982d89SJeremy L. Thompson 
312ca94c3ddSJeremy L Thompson   @param[in]  rstr         `CeedElemRestriction` to retrieve curl-conforming orientations
313fcbe8c06SSebastian Grimberg   @param[in]  mem_type     Memory type on which to access the array.
314fcbe8c06SSebastian Grimberg                              If the backend uses a different memory type, this will perform a copy (possibly cached).
315ca94c3ddSJeremy L Thompson   @param[out] curl_orients Array on memory type `mem_type`
3167a982d89SJeremy L. Thompson 
3177a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3187a982d89SJeremy L. Thompson 
31977d1c127SSebastian Grimberg   @ref User
3207a982d89SJeremy L. Thompson **/
3210c73c039SSebastian Grimberg int CeedElemRestrictionGetCurlOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt8 **curl_orients) {
3226e536b99SJeremy L Thompson   CeedCheck(rstr->GetCurlOrientations, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED,
3236e536b99SJeremy L Thompson             "Backend does not support CeedElemRestrictionGetCurlOrientations");
32477d1c127SSebastian Grimberg   CeedCall(rstr->GetCurlOrientations(rstr, mem_type, curl_orients));
32577d1c127SSebastian Grimberg   rstr->num_readers++;
32677d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
32777d1c127SSebastian Grimberg }
32877d1c127SSebastian Grimberg 
32977d1c127SSebastian Grimberg /**
330ca94c3ddSJeremy L Thompson   @brief Restore an orientations array obtained using @ref CeedElemRestrictionGetCurlOrientations()
33177d1c127SSebastian Grimberg 
332ca94c3ddSJeremy L Thompson   @param[in] rstr         `CeedElemRestriction` to restore
33377d1c127SSebastian Grimberg   @param[in] curl_orients Array of orientation data
33477d1c127SSebastian Grimberg 
33577d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
33677d1c127SSebastian Grimberg 
33777d1c127SSebastian Grimberg   @ref User
33877d1c127SSebastian Grimberg **/
3390c73c039SSebastian Grimberg int CeedElemRestrictionRestoreCurlOrientations(CeedElemRestriction rstr, const CeedInt8 **curl_orients) {
34077d1c127SSebastian Grimberg   *curl_orients = NULL;
34177d1c127SSebastian Grimberg   rstr->num_readers--;
342e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3437a982d89SJeremy L. Thompson }
3447a982d89SJeremy L. Thompson 
3457a982d89SJeremy L. Thompson /**
34649fd234cSJeremy L Thompson 
34722eb1385SJeremy L Thompson   @brief Get the L-vector layout of a strided `CeedElemRestriction`
34822eb1385SJeremy L Thompson 
34922eb1385SJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
35022eb1385SJeremy L Thompson   @param[out] layout  Variable to store layout array, stored as `[nodes, components, elements]`.
35122eb1385SJeremy L Thompson                         The data for node `i`, component `j`, element `k` in the E-vector is given by `i*layout[0] + j*layout[1] + k*layout[2]`.
35222eb1385SJeremy L Thompson 
35322eb1385SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
35422eb1385SJeremy L Thompson 
35522eb1385SJeremy L Thompson   @ref Backend
35622eb1385SJeremy L Thompson **/
35756c48462SJeremy L Thompson int CeedElemRestrictionGetLLayout(CeedElemRestriction rstr, CeedInt layout[3]) {
35822eb1385SJeremy L Thompson   bool                has_backend_strides;
35922eb1385SJeremy L Thompson   CeedRestrictionType rstr_type;
3601203703bSJeremy L Thompson   Ceed                ceed;
36122eb1385SJeremy L Thompson 
3621203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
36322eb1385SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
3641203703bSJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_STRIDED, ceed, CEED_ERROR_MINOR, "Only strided CeedElemRestriction have strided L-vector layout");
36522eb1385SJeremy L Thompson   CeedCall(CeedElemRestrictionHasBackendStrides(rstr, &has_backend_strides));
36622eb1385SJeremy L Thompson   if (has_backend_strides) {
3671203703bSJeremy L Thompson     CeedCheck(rstr->l_layout[0], ceed, CEED_ERROR_MINOR, "CeedElemRestriction has no L-vector layout data");
36856c48462SJeremy L Thompson     for (CeedInt i = 0; i < 3; i++) layout[i] = rstr->l_layout[i];
36922eb1385SJeremy L Thompson   } else {
37022eb1385SJeremy L Thompson     CeedCall(CeedElemRestrictionGetStrides(rstr, layout));
37122eb1385SJeremy L Thompson   }
37222eb1385SJeremy L Thompson   return CEED_ERROR_SUCCESS;
37322eb1385SJeremy L Thompson }
37422eb1385SJeremy L Thompson 
37522eb1385SJeremy L Thompson /**
37622eb1385SJeremy L Thompson 
37722eb1385SJeremy L Thompson   @brief Set the L-vector layout of a strided `CeedElemRestriction`
37822eb1385SJeremy L Thompson 
37922eb1385SJeremy L Thompson   @param[in] rstr   `CeedElemRestriction`
38022eb1385SJeremy L Thompson   @param[in] layout Variable to containing layout array, stored as `[nodes, components, elements]`.
38122eb1385SJeremy L Thompson                       The data for node `i`, component `j`, element `k` in the E-vector is given by `i*layout[0] + j*layout[1] + k*layout[2]`.
38222eb1385SJeremy L Thompson 
38322eb1385SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
38422eb1385SJeremy L Thompson 
38522eb1385SJeremy L Thompson   @ref Backend
38622eb1385SJeremy L Thompson **/
38722eb1385SJeremy L Thompson int CeedElemRestrictionSetLLayout(CeedElemRestriction rstr, CeedInt layout[3]) {
38822eb1385SJeremy L Thompson   CeedRestrictionType rstr_type;
38922eb1385SJeremy L Thompson 
39022eb1385SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
3916e536b99SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_STRIDED, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR,
3926e536b99SJeremy L Thompson             "Only strided CeedElemRestriction have strided L-vector layout");
39322eb1385SJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) rstr->l_layout[i] = layout[i];
39422eb1385SJeremy L Thompson   return CEED_ERROR_SUCCESS;
39522eb1385SJeremy L Thompson }
39622eb1385SJeremy L Thompson 
39722eb1385SJeremy L Thompson /**
39822eb1385SJeremy L Thompson 
399ca94c3ddSJeremy L Thompson   @brief Get the E-vector layout of a `CeedElemRestriction`
40049fd234cSJeremy L Thompson 
401ca94c3ddSJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
402ca94c3ddSJeremy L Thompson   @param[out] layout  Variable to store layout array, stored as `[nodes, components, elements]`.
403ca94c3ddSJeremy L Thompson                         The data for node `i`, component `j`, element `k` in the E-vector is given by `i*layout[0] + j*layout[1] + k*layout[2]`.
40449fd234cSJeremy L Thompson 
40549fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
40649fd234cSJeremy L Thompson 
40749fd234cSJeremy L Thompson   @ref Backend
40849fd234cSJeremy L Thompson **/
40956c48462SJeremy L Thompson int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
4106e536b99SJeremy L Thompson   CeedCheck(rstr->e_layout[0], CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, "CeedElemRestriction has no E-vector layout data");
41156c48462SJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) layout[i] = rstr->e_layout[i];
412e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
41349fd234cSJeremy L Thompson }
41449fd234cSJeremy L Thompson 
41549fd234cSJeremy L Thompson /**
41649fd234cSJeremy L Thompson 
417ca94c3ddSJeremy L Thompson   @brief Set the E-vector layout of a `CeedElemRestriction`
41849fd234cSJeremy L Thompson 
419ca94c3ddSJeremy L Thompson   @param[in] rstr   `CeedElemRestriction`
420ca94c3ddSJeremy L Thompson   @param[in] layout Variable to containing layout array, stored as `[nodes, components, elements]`.
421ca94c3ddSJeremy L Thompson                       The data for node `i`, component `j`, element `k` in the E-vector is given by `i*layout[0] + j*layout[1] + k*layout[2]`.
42249fd234cSJeremy L Thompson 
42349fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
42449fd234cSJeremy L Thompson 
42549fd234cSJeremy L Thompson   @ref Backend
42649fd234cSJeremy L Thompson **/
4272b730f8bSJeremy L Thompson int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
42822eb1385SJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) rstr->e_layout[i] = layout[i];
429e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
43049fd234cSJeremy L Thompson }
43149fd234cSJeremy L Thompson 
43249fd234cSJeremy L Thompson /**
433*19605835SJeremy L Thompson 
434*19605835SJeremy L Thompson   @brief Get the E-vector element offset of a `CeedElemRestriction` at points
435*19605835SJeremy L Thompson 
436*19605835SJeremy L Thompson   @param[in]  rstr        `CeedElemRestriction`
437*19605835SJeremy L Thompson   @param[in]  elem        Element number index into E-vector for
438*19605835SJeremy L Thompson   @param[out] elem_offset Offset for element `elem` in the E-vector.
439*19605835SJeremy L Thompson                             The data for point `i`, component `j`, element `elem` in the E-vector is given by `i*e_layout[0] + j*e_layout[1] + elem_offset`.
440*19605835SJeremy L Thompson 
441*19605835SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
442*19605835SJeremy L Thompson 
443*19605835SJeremy L Thompson   @ref Backend
444*19605835SJeremy L Thompson **/
445*19605835SJeremy L Thompson int CeedElemRestrictionGetAtPointsElementOffset(CeedElemRestriction rstr, CeedInt elem, CeedSize *elem_offset) {
446*19605835SJeremy L Thompson   CeedInt             num_comp;
447*19605835SJeremy L Thompson   CeedRestrictionType rstr_type;
448*19605835SJeremy L Thompson 
449*19605835SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
450*19605835SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
451*19605835SJeremy L Thompson             "Can only compute offset for a points CeedElemRestriction");
452*19605835SJeremy L Thompson 
453*19605835SJeremy L Thompson   // Backend method
454*19605835SJeremy L Thompson   if (rstr->GetAtPointsElementOffset) {
455*19605835SJeremy L Thompson     CeedCall(rstr->GetAtPointsElementOffset(rstr, elem, elem_offset));
456*19605835SJeremy L Thompson     return CEED_ERROR_SUCCESS;
457*19605835SJeremy L Thompson   }
458*19605835SJeremy L Thompson 
459*19605835SJeremy L Thompson   // Default layout (CPU)
460*19605835SJeremy L Thompson   *elem_offset = 0;
461*19605835SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
462*19605835SJeremy L Thompson   for (CeedInt i = 0; i < elem; i++) {
463*19605835SJeremy L Thompson     CeedInt num_points;
464*19605835SJeremy L Thompson 
465*19605835SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, i, &num_points));
466*19605835SJeremy L Thompson     *elem_offset += num_points * num_comp;
467*19605835SJeremy L Thompson   }
468*19605835SJeremy L Thompson   return CEED_ERROR_SUCCESS;
469*19605835SJeremy L Thompson }
470*19605835SJeremy L Thompson 
471*19605835SJeremy L Thompson /**
472ca94c3ddSJeremy L Thompson   @brief Get the backend data of a `CeedElemRestriction`
4737a982d89SJeremy L. Thompson 
474ca94c3ddSJeremy L Thompson   @param[in]  rstr `CeedElemRestriction`
4757a982d89SJeremy L. Thompson   @param[out] data Variable to store data
4767a982d89SJeremy L. Thompson 
4777a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4787a982d89SJeremy L. Thompson 
4797a982d89SJeremy L. Thompson   @ref Backend
4807a982d89SJeremy L. Thompson **/
481777ff853SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) {
482777ff853SJeremy L Thompson   *(void **)data = rstr->data;
483e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4847a982d89SJeremy L. Thompson }
4857a982d89SJeremy L. Thompson 
4867a982d89SJeremy L. Thompson /**
487ca94c3ddSJeremy L Thompson   @brief Set the backend data of a `CeedElemRestriction`
4887a982d89SJeremy L. Thompson 
489ca94c3ddSJeremy L Thompson   @param[in,out] rstr `CeedElemRestriction`
490ea61e9acSJeremy L Thompson   @param[in]     data Data to set
4917a982d89SJeremy L. Thompson 
4927a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4937a982d89SJeremy L. Thompson 
4947a982d89SJeremy L. Thompson   @ref Backend
4957a982d89SJeremy L. Thompson **/
496777ff853SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) {
497777ff853SJeremy L Thompson   rstr->data = data;
498e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4997a982d89SJeremy L. Thompson }
5007a982d89SJeremy L. Thompson 
50134359f16Sjeremylt /**
502ca94c3ddSJeremy L Thompson   @brief Increment the reference counter for a `CeedElemRestriction`
50334359f16Sjeremylt 
504ca94c3ddSJeremy L Thompson   @param[in,out] rstr `CeedElemRestriction` to increment the reference counter
50534359f16Sjeremylt 
50634359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
50734359f16Sjeremylt 
50834359f16Sjeremylt   @ref Backend
50934359f16Sjeremylt **/
5109560d06aSjeremylt int CeedElemRestrictionReference(CeedElemRestriction rstr) {
51134359f16Sjeremylt   rstr->ref_count++;
51234359f16Sjeremylt   return CEED_ERROR_SUCCESS;
51334359f16Sjeremylt }
51434359f16Sjeremylt 
5156e15d496SJeremy L Thompson /**
516ca94c3ddSJeremy L Thompson   @brief Estimate number of FLOPs required to apply `CeedElemRestriction` in `t_mode`
5176e15d496SJeremy L Thompson 
518ca94c3ddSJeremy L Thompson   @param[in]  rstr   `CeedElemRestriction` to estimate FLOPs for
519ea61e9acSJeremy L Thompson   @param[in]  t_mode Apply restriction or transpose
520ea61e9acSJeremy L Thompson   @param[out] flops  Address of variable to hold FLOPs estimate
5216e15d496SJeremy L Thompson 
5226e15d496SJeremy L Thompson   @ref Backend
5236e15d496SJeremy L Thompson **/
5242b730f8bSJeremy L Thompson int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedSize *flops) {
5251203703bSJeremy L Thompson   CeedSize            e_size, scale = 0;
52689edb9e3SSebastian Grimberg   CeedRestrictionType rstr_type;
5271c66c397SJeremy L Thompson 
5281203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &e_size));
52989edb9e3SSebastian Grimberg   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
53077d1c127SSebastian Grimberg   if (t_mode == CEED_TRANSPOSE) {
53189edb9e3SSebastian Grimberg     switch (rstr_type) {
5323ac8f562SJeremy L Thompson       case CEED_RESTRICTION_POINTS:
5333ac8f562SJeremy L Thompson         scale = 0;
5343ac8f562SJeremy L Thompson         break;
53589edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STRIDED:
53689edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STANDARD:
53777d1c127SSebastian Grimberg         scale = 1;
53889edb9e3SSebastian Grimberg         break;
53989edb9e3SSebastian Grimberg       case CEED_RESTRICTION_ORIENTED:
54077d1c127SSebastian Grimberg         scale = 2;
54189edb9e3SSebastian Grimberg         break;
54289edb9e3SSebastian Grimberg       case CEED_RESTRICTION_CURL_ORIENTED:
54377d1c127SSebastian Grimberg         scale = 6;
54489edb9e3SSebastian Grimberg         break;
5456e15d496SJeremy L Thompson     }
54677d1c127SSebastian Grimberg   } else {
54789edb9e3SSebastian Grimberg     switch (rstr_type) {
54889edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STRIDED:
54989edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STANDARD:
5503ac8f562SJeremy L Thompson       case CEED_RESTRICTION_POINTS:
55177d1c127SSebastian Grimberg         scale = 0;
55289edb9e3SSebastian Grimberg         break;
55389edb9e3SSebastian Grimberg       case CEED_RESTRICTION_ORIENTED:
55477d1c127SSebastian Grimberg         scale = 1;
55589edb9e3SSebastian Grimberg         break;
55689edb9e3SSebastian Grimberg       case CEED_RESTRICTION_CURL_ORIENTED:
55777d1c127SSebastian Grimberg         scale = 5;
55889edb9e3SSebastian Grimberg         break;
55977d1c127SSebastian Grimberg     }
56077d1c127SSebastian Grimberg   }
5616e15d496SJeremy L Thompson   *flops = e_size * scale;
5626e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5636e15d496SJeremy L Thompson }
5646e15d496SJeremy L Thompson 
5657a982d89SJeremy L. Thompson /// @}
5667a982d89SJeremy L. Thompson 
56715910d16Sjeremylt /// @cond DOXYGEN_SKIP
56815910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
56915910d16Sjeremylt /// @endcond
57015910d16Sjeremylt 
5717a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5727a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
5737a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5747a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
575d7b241e6Sjeremylt /// @{
576d7b241e6Sjeremylt 
5777a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
57845f1e315Sjeremylt const CeedInt CEED_STRIDES_BACKEND[3] = {0};
5797a982d89SJeremy L. Thompson 
580ca94c3ddSJeremy L Thompson /// Argument for @ref CeedOperatorSetField() indicating that the field does not require a `CeedElemRestriction`
5812b730f8bSJeremy L Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = &ceed_elemrestriction_none;
5827a982d89SJeremy L. Thompson 
583d7b241e6Sjeremylt /**
584ca94c3ddSJeremy L Thompson   @brief Create a `CeedElemRestriction`
585d7b241e6Sjeremylt 
586ca94c3ddSJeremy L Thompson   @param[in]  ceed        `Ceed` context used to create the `CeedElemRestriction`
587ca94c3ddSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the `offsets` array
588ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
589ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
590fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
591ca94c3ddSJeremy L Thompson                             Data for node `i`, component `j`, element `k` can be found in the L-vector at index `offsets[i + k*elem_size] + j*comp_stride`.
592fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
593fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
594ca94c3ddSJeremy L Thompson   @param[in]  mem_type    Memory type of the `offsets` array, see @ref CeedMemType
595ca94c3ddSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the `offsets` array, see @ref CeedCopyMode
596ca94c3ddSJeremy L Thompson   @param[in]  offsets     Array of shape `[num_elem, elem_size]`.
597ca94c3ddSJeremy L Thompson                             Row `i` holds the ordered list of the offsets (into the input `CeedVector`) for the unknowns corresponding to element `i`, where 0 <= i < @a num_elem.
598ca94c3ddSJeremy L Thompson                             All offsets must be in the range `[0, l_size - 1]`.
599ca94c3ddSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created `CeedElemRestriction` will be stored
600d7b241e6Sjeremylt 
601b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
602dfdf5a53Sjeremylt 
6037a982d89SJeremy L. Thompson   @ref User
604b11c1e72Sjeremylt **/
6052b730f8bSJeremy L Thompson int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
6062b730f8bSJeremy L Thompson                               CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
6075fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
6085fe0d4faSjeremylt     Ceed delegate;
6096574a04fSJeremy L Thompson 
6102b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
611ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreate");
6122b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
613e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6145fe0d4faSjeremylt   }
6155fe0d4faSjeremylt 
616e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
6176574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
618ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
619ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
620e022e1f8SJeremy L Thompson 
6212b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
622db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
623d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
624d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
625d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
626d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
627d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
628d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
6291203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp;
630e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
631e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
63261a27d74SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_STANDARD;
633fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, NULL, *rstr));
634e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
635d7b241e6Sjeremylt }
636d7b241e6Sjeremylt 
637d7b241e6Sjeremylt /**
638ca94c3ddSJeremy L Thompson   @brief Create a `CeedElemRestriction` with orientation signs
639fc0567d9Srezgarshakeri 
640ca94c3ddSJeremy L Thompson   @param[in]  ceed        `Ceed` context used to create the `CeedElemRestriction`
641ca94c3ddSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the `offsets` array
642ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
643ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
644fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
645ca94c3ddSJeremy L Thompson                             Data for node `i`, component `j`, element `k` can be found in the L-vector at index `offsets[i + k*elem_size] + j*comp_stride`.
646fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
647fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
648ca94c3ddSJeremy L Thompson   @param[in]  mem_type    Memory type of the `offsets` array, see @ref CeedMemType
649ca94c3ddSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the `offsets` array, see @ref CeedCopyMode
650ca94c3ddSJeremy L Thompson   @param[in]  offsets     Array of shape `[num_elem, elem_size]`.
651ca94c3ddSJeremy L Thompson                             Row i holds the ordered list of the offsets (into the input `CeedVector`) for the unknowns corresponding to element `i`, where `0 <= i < num_elem`.
652ca94c3ddSJeremy L Thompson                             All offsets must be in the range `[0, l_size - 1]`.
653ca94c3ddSJeremy L Thompson   @param[in]  orients     Boolean array of shape `[num_elem, elem_size]` with `false` for positively oriented and `true` to flip the orientation
654ca94c3ddSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created `CeedElemRestriction` will be stored
655fc0567d9Srezgarshakeri 
656fc0567d9Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
657fc0567d9Srezgarshakeri 
658fc0567d9Srezgarshakeri   @ref User
659fc0567d9Srezgarshakeri **/
6602b730f8bSJeremy L Thompson int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
66177d1c127SSebastian Grimberg                                       CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orients,
662fc0567d9Srezgarshakeri                                       CeedElemRestriction *rstr) {
663fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreate) {
664fc0567d9Srezgarshakeri     Ceed delegate;
6656574a04fSJeremy L Thompson 
6662b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
667ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateOriented");
6682b730f8bSJeremy L Thompson     CeedCall(
66977d1c127SSebastian Grimberg         CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, orients, rstr));
670fc0567d9Srezgarshakeri     return CEED_ERROR_SUCCESS;
671fc0567d9Srezgarshakeri   }
672fc0567d9Srezgarshakeri 
673e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
6746574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
675ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
676ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
677e022e1f8SJeremy L Thompson 
6782b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
679db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
680fc0567d9Srezgarshakeri   (*rstr)->ref_count   = 1;
681fc0567d9Srezgarshakeri   (*rstr)->num_elem    = num_elem;
682fc0567d9Srezgarshakeri   (*rstr)->elem_size   = elem_size;
683fc0567d9Srezgarshakeri   (*rstr)->num_comp    = num_comp;
684fc0567d9Srezgarshakeri   (*rstr)->comp_stride = comp_stride;
685fc0567d9Srezgarshakeri   (*rstr)->l_size      = l_size;
6861203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp;
687e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
688e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
689fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_ORIENTED;
690fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, orients, NULL, *rstr));
69177d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
69277d1c127SSebastian Grimberg }
69377d1c127SSebastian Grimberg 
69477d1c127SSebastian Grimberg /**
695ca94c3ddSJeremy L Thompson   @brief Create a `CeedElemRestriction` with a general tridiagonal transformation matrix for curl-conforming elements
69677d1c127SSebastian Grimberg 
697ca94c3ddSJeremy L Thompson   @param[in]  ceed         `Ceed` context used to create the `CeedElemRestriction`
698ca94c3ddSJeremy L Thompson   @param[in]  num_elem     Number of elements described in the `offsets` array
69977d1c127SSebastian Grimberg   @param[in]  elem_size    Size (number of "nodes") per element
70077d1c127SSebastian Grimberg   @param[in]  num_comp     Number of field components per interpolation node (1 for scalar fields)
701fcbe8c06SSebastian Grimberg   @param[in]  comp_stride  Stride between components for the same L-vector "node".
702ca94c3ddSJeremy L Thompson                              Data for node `i`, component `j`, element `k` can be found in the L-vector at index `offsets[i + k*elem_size] + j*comp_stride`.
703fcbe8c06SSebastian Grimberg   @param[in]  l_size       The size of the L-vector.
704fcbe8c06SSebastian Grimberg                              This vector may be larger than the elements and fields given by this restriction.
705ca94c3ddSJeremy L Thompson   @param[in]  mem_type     Memory type of the `offsets` array, see @ref CeedMemType
706ca94c3ddSJeremy L Thompson   @param[in]  copy_mode    Copy mode for the `offsets` array, see @ref CeedCopyMode
707ca94c3ddSJeremy L Thompson   @param[in]  offsets      Array of shape `[num_elem, elem_size]`.
708ca94c3ddSJeremy L Thompson                              Row `i` holds the ordered list of the offsets (into the input `CeedVector`) for the unknowns corresponding to element `i`, where `0 <= i < num_elem`.
709ca94c3ddSJeremy L Thompson                              All offsets must be in the range `[0, l_size - 1]`.
710ca94c3ddSJeremy L Thompson   @param[in]  curl_orients Array of shape `[num_elem, 3 * elem_size]` representing a row-major tridiagonal matrix (`curl_orients[i * 3 * elem_size] = curl_orients[(i + 1) * 3 * elem_size - 1] = 0`, where `0 <= i < num_elem`) which is applied to the element unknowns upon restriction.
711ca94c3ddSJeremy L Thompson                              This orientation matrix allows for pairs of face degrees of freedom on elements for \f$H(\mathrm{curl})\f$ spaces to be coupled in the element restriction operation, which is a way to resolve face orientation issues for 3D meshes (https://dl.acm.org/doi/pdf/10.1145/3524456).
712ca94c3ddSJeremy L Thompson   @param[out] rstr         Address of the variable where the newly created `CeedElemRestriction` will be stored
71377d1c127SSebastian Grimberg 
71477d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
71577d1c127SSebastian Grimberg 
71677d1c127SSebastian Grimberg   @ref User
71777d1c127SSebastian Grimberg **/
71877d1c127SSebastian Grimberg int CeedElemRestrictionCreateCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
7190c73c039SSebastian Grimberg                                           CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const CeedInt8 *curl_orients,
72077d1c127SSebastian Grimberg                                           CeedElemRestriction *rstr) {
721fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreate) {
72277d1c127SSebastian Grimberg     Ceed delegate;
72377d1c127SSebastian Grimberg 
72477d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
725ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateCurlOriented");
72677d1c127SSebastian Grimberg     CeedCall(CeedElemRestrictionCreateCurlOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
72777d1c127SSebastian Grimberg                                                    curl_orients, rstr));
72877d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
72977d1c127SSebastian Grimberg   }
73077d1c127SSebastian Grimberg 
731e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
73277d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
733ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
734ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
73577d1c127SSebastian Grimberg 
73677d1c127SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
737fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
73877d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
73977d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
74077d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
74177d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
74277d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
74377d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
7441203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp;
745e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
746e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
747fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_CURL_ORIENTED;
748fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, curl_orients, *rstr));
749fc0567d9Srezgarshakeri   return CEED_ERROR_SUCCESS;
750fc0567d9Srezgarshakeri }
751fc0567d9Srezgarshakeri 
752fc0567d9Srezgarshakeri /**
753ca94c3ddSJeremy L Thompson   @brief Create a strided `CeedElemRestriction`
754d7b241e6Sjeremylt 
755ca94c3ddSJeremy L Thompson   @param[in]  ceed      `Ceed` context used to create the `CeedElemRestriction`
756ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
757ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
758ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation "node" (1 for scalar fields)
759fcbe8c06SSebastian Grimberg   @param[in]  l_size    The size of the L-vector.
760fcbe8c06SSebastian Grimberg                           This vector may be larger than the elements and fields given by this restriction.
761ca94c3ddSJeremy L Thompson   @param[in]  strides   Array for strides between `[nodes, components, elements]`.
762ca94c3ddSJeremy L Thompson                           Data for node `i`, component `j`, element `k` can be found in the L-vector at index `i*strides[0] + j*strides[1] + k*strides[2]`.
763ca94c3ddSJeremy L Thompson                           @ref CEED_STRIDES_BACKEND may be used for `CeedVector` ordered by the same `Ceed` backend.
764972f909dSJeremy L Thompson                           `CEED_STRIDES_BACKEND` should only be used pass data between `CeedOperator` created with the same `Ceed` backend.
765972f909dSJeremy L Thompson                           The L-vector layout will, in general, be different between `Ceed` backends.
766ca94c3ddSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created `CeedElemRestriction` will be stored
767d7b241e6Sjeremylt 
768b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
769dfdf5a53Sjeremylt 
7707a982d89SJeremy L. Thompson   @ref User
771b11c1e72Sjeremylt **/
7722b730f8bSJeremy L Thompson int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedSize l_size, const CeedInt strides[3],
773f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
7745fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
7755fe0d4faSjeremylt     Ceed delegate;
776b04eb3d9SSebastian Grimberg 
7772b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
778ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateStrided");
7792b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, l_size, strides, rstr));
780e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
7815fe0d4faSjeremylt   }
7825fe0d4faSjeremylt 
783e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
7846574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
785ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
78681670346SSebastian Grimberg   CeedCheck(l_size >= (CeedSize)num_elem * elem_size * num_comp, ceed, CEED_ERROR_DIMENSION,
78781670346SSebastian Grimberg             "L-vector size must be at least num_elem * elem_size * num_comp");
788e022e1f8SJeremy L Thompson 
7892b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
790db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
791d1d35e2fSjeremylt   (*rstr)->ref_count  = 1;
792d1d35e2fSjeremylt   (*rstr)->num_elem   = num_elem;
793d1d35e2fSjeremylt   (*rstr)->elem_size  = elem_size;
794d1d35e2fSjeremylt   (*rstr)->num_comp   = num_comp;
795d1d35e2fSjeremylt   (*rstr)->l_size     = l_size;
7961203703bSJeremy L Thompson   (*rstr)->e_size     = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp;
797e7f679fcSJeremy L Thompson   (*rstr)->num_block  = num_elem;
798e7f679fcSJeremy L Thompson   (*rstr)->block_size = 1;
799fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type  = CEED_RESTRICTION_STRIDED;
8002b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
8012b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
802fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
803e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
804d7b241e6Sjeremylt }
805d7b241e6Sjeremylt 
806d7b241e6Sjeremylt /**
807ca94c3ddSJeremy L Thompson   @brief Create a points `CeedElemRestriction`, for restricting for restricting from a all local points to the current element in which they are located.
8083ac8f562SJeremy L Thompson 
8093ac8f562SJeremy L Thompson   The offsets array is arranged as
8103ac8f562SJeremy L Thompson 
8113ac8f562SJeremy L Thompson   element_0_start_index
8123ac8f562SJeremy L Thompson   element_1_start_index
8133ac8f562SJeremy L Thompson   ...
8143ac8f562SJeremy L Thompson   element_n_start_index
8153ac8f562SJeremy L Thompson   element_n_stop_index
8163ac8f562SJeremy L Thompson   element_0_point_0
8173ac8f562SJeremy L Thompson   element_0_point_1
8183ac8f562SJeremy L Thompson   ...
8193ac8f562SJeremy L Thompson 
820ca94c3ddSJeremy L Thompson   @param[in]  ceed       `Ceed` context used to create the `CeedElemRestriction`
821ca94c3ddSJeremy L Thompson   @param[in]  num_elem   Number of elements described in the `offsets` array
822ca94c3ddSJeremy L Thompson   @param[in]  num_points Number of points described in the `offsets` array
8233ac8f562SJeremy L Thompson   @param[in]  num_comp   Number of field components per interpolation node (1 for scalar fields).
8243ac8f562SJeremy L Thompson                            Components are assumed to be contiguous by point.
8253ac8f562SJeremy L Thompson   @param[in]  l_size     The size of the L-vector.
8263ac8f562SJeremy L Thompson                            This vector may be larger than the elements and fields given by this restriction.
827ca94c3ddSJeremy L Thompson   @param[in]  mem_type   Memory type of the `offsets` array, see @ref CeedMemType
828ca94c3ddSJeremy L Thompson   @param[in]  copy_mode  Copy mode for the `offsets` array, see @ref CeedCopyMode
829ca94c3ddSJeremy L Thompson   @param[in]  offsets    Array of size `num_elem + 1 + num_points`.
8303ac8f562SJeremy L Thompson                            The first portion of the offsets array holds the ranges of indices corresponding to each element.
8313ac8f562SJeremy L Thompson                            The second portion holds the indices for each element.
832ca94c3ddSJeremy L Thompson   @param[out] rstr       Address of the variable where the newly created `CeedElemRestriction` will be stored
8333ac8f562SJeremy L Thompson 
8343ac8f562SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
8353ac8f562SJeremy L Thompson 
8363ac8f562SJeremy L Thompson   @ref Backend
8373ac8f562SJeremy L Thompson  **/
8383ac8f562SJeremy L Thompson int CeedElemRestrictionCreateAtPoints(Ceed ceed, CeedInt num_elem, CeedInt num_points, CeedInt num_comp, CeedSize l_size, CeedMemType mem_type,
8393ac8f562SJeremy L Thompson                                       CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
8403ac8f562SJeremy L Thompson   if (!ceed->ElemRestrictionCreateAtPoints) {
8413ac8f562SJeremy L Thompson     Ceed delegate;
8423ac8f562SJeremy L Thompson 
8433ac8f562SJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
844ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateAtPoints");
8453ac8f562SJeremy L Thompson     CeedCall(CeedElemRestrictionCreateAtPoints(delegate, num_elem, num_points, num_comp, l_size, mem_type, copy_mode, offsets, rstr));
8463ac8f562SJeremy L Thompson     return CEED_ERROR_SUCCESS;
8473ac8f562SJeremy L Thompson   }
8483ac8f562SJeremy L Thompson 
8493ac8f562SJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
8503ac8f562SJeremy L Thompson   CeedCheck(num_points >= 0, ceed, CEED_ERROR_DIMENSION, "Number of points must be non-negative");
851ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
85281670346SSebastian Grimberg   CeedCheck(l_size >= (CeedSize)num_points * num_comp, ceed, CEED_ERROR_DIMENSION, "L-vector must be at least num_points * num_comp");
8533ac8f562SJeremy L Thompson 
8543ac8f562SJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
8553ac8f562SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
8563ac8f562SJeremy L Thompson   (*rstr)->ref_count  = 1;
8573ac8f562SJeremy L Thompson   (*rstr)->num_elem   = num_elem;
8583ac8f562SJeremy L Thompson   (*rstr)->num_points = num_points;
8593ac8f562SJeremy L Thompson   (*rstr)->num_comp   = num_comp;
8603ac8f562SJeremy L Thompson   (*rstr)->l_size     = l_size;
8611203703bSJeremy L Thompson   (*rstr)->e_size     = (CeedSize)num_points * (CeedSize)num_comp;
86205fa913cSJeremy L Thompson   (*rstr)->num_block  = num_elem;
8633ac8f562SJeremy L Thompson   (*rstr)->block_size = 1;
8643ac8f562SJeremy L Thompson   (*rstr)->rstr_type  = CEED_RESTRICTION_POINTS;
8653ac8f562SJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateAtPoints(mem_type, copy_mode, offsets, NULL, NULL, *rstr));
8663ac8f562SJeremy L Thompson   return CEED_ERROR_SUCCESS;
8673ac8f562SJeremy L Thompson }
8683ac8f562SJeremy L Thompson 
8693ac8f562SJeremy L Thompson /**
870ca94c3ddSJeremy L Thompson   @brief Create a blocked `CeedElemRestriction`, typically only used by backends
871d7b241e6Sjeremylt 
872ca94c3ddSJeremy L Thompson   @param[in]  ceed        `Ceed` context used to create the `CeedElemRestriction`
873ca94c3ddSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the `offsets` array
874ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of unknowns) per element
875e7f679fcSJeremy L Thompson   @param[in]  block_size  Number of elements in a block
876ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
877fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
878ca94c3ddSJeremy L Thompson                             Data for node `i`, component `j`, element `k` can be found in the L-vector at index `offsets[i + k*elem_size] + j*comp_stride`.
879fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
880fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
881ca94c3ddSJeremy L Thompson   @param[in]  mem_type    Memory type of the `offsets` array, see @ref CeedMemType
882ca94c3ddSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the `offsets` array, see @ref CeedCopyMode
883ca94c3ddSJeremy L Thompson   @param[in]  offsets     Array of shape `[num_elem, elem_size]`.
884ca94c3ddSJeremy L Thompson                             Row `i` holds the ordered list of the offsets (into the input `CeedVector`) for the unknowns corresponding to element `i`, where `0 <= i < num_elem`.
885ca94c3ddSJeremy L Thompson                             All offsets must be in the range `[0, l_size - 1]`.
886ca94c3ddSJeremy L Thompson                             The backend will permute and pad this array to the desired ordering for the blocksize, which is typically given by the backend.
887ca94c3ddSJeremy L Thompson                             The default reordering is to interlace elements.
888ca94c3ddSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created `CeedElemRestriction` will be stored
889d7b241e6Sjeremylt 
890b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
891dfdf5a53Sjeremylt 
8927a982d89SJeremy L. Thompson   @ref Backend
893b11c1e72Sjeremylt  **/
894e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedInt comp_stride,
8952b730f8bSJeremy L Thompson                                      CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets,
8964ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
8971c66c397SJeremy L Thompson   CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
898d7b241e6Sjeremylt 
8995fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
9005fe0d4faSjeremylt     Ceed delegate;
9016574a04fSJeremy L Thompson 
9022b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
903ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlocked");
904e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
905e7f679fcSJeremy L Thompson                                               rstr));
906e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
9075fe0d4faSjeremylt   }
908d7b241e6Sjeremylt 
909e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
9106574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
911e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
912ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
913ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
914e022e1f8SJeremy L Thompson 
915e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
916e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
917d7b241e6Sjeremylt 
918db002c03SJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
919db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
920d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
921d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
922d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
923d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
924d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
925d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
9261203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
927e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
928e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
92961a27d74SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_STANDARD;
930e7f679fcSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL, NULL, *rstr));
9311c66c397SJeremy L Thompson   if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
932e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
933d7b241e6Sjeremylt }
934d7b241e6Sjeremylt 
935b11c1e72Sjeremylt /**
936ca94c3ddSJeremy L Thompson   @brief Create a blocked oriented `CeedElemRestriction`, typically only used by backends
93777d1c127SSebastian Grimberg 
938ca94c3ddSJeremy L Thompson   @param[in]  ceed        `Ceed` context used to create the `CeedElemRestriction`
939ca94c3ddSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the `offsets` array.
94077d1c127SSebastian Grimberg   @param[in]  elem_size   Size (number of unknowns) per element
941e7f679fcSJeremy L Thompson   @param[in]  block_size  Number of elements in a block
94277d1c127SSebastian Grimberg   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
943fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
944ca94c3ddSJeremy L Thompson                             Data for node `i`, component `j`, element `k` can be found in the L-vector at index `offsets[i + k*elem_size] + j*comp_stride`.
945fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
946fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
947ca94c3ddSJeremy L Thompson   @param[in]  mem_type    Memory type of the `offsets` array, see @ref CeedMemType
948ca94c3ddSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the `offsets` array, see @ref CeedCopyMode
949ca94c3ddSJeremy L Thompson   @param[in]  offsets     Array of shape `[num_elem, elem_size]`.
950ca94c3ddSJeremy L Thompson                             Row `i` holds the ordered list of the offsets (into the input `CeedVector`) for the unknowns corresponding to element `i`, where `0 <= i < num_elem`.
951ca94c3ddSJeremy L Thompson                             All offsets must be in the range `[0, l_size - 1]`.
952ca94c3ddSJeremy L Thompson                             The backend will permute and pad this array to the desired ordering for the blocksize, which is typically given by the backend.
953ca94c3ddSJeremy L Thompson                             The default reordering is to interlace elements.
954ca94c3ddSJeremy L Thompson   @param[in]  orients     Boolean array of shape `[num_elem, elem_size]` with `false` for positively oriented and `true` to flip the orientation.
955ca94c3ddSJeremy L Thompson                             Will also be permuted and padded similarly to `offsets`.
956ca94c3ddSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created `CeedElemRestriction` will be stored
95777d1c127SSebastian Grimberg 
95877d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
95977d1c127SSebastian Grimberg 
96077d1c127SSebastian Grimberg   @ref Backend
96177d1c127SSebastian Grimberg  **/
962e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp,
963e7f679fcSJeremy L Thompson                                              CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode,
964e7f679fcSJeremy L Thompson                                              const CeedInt *offsets, const bool *orients, CeedElemRestriction *rstr) {
965e7f679fcSJeremy L Thompson   bool    *block_orients;
9661c66c397SJeremy L Thompson   CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
96777d1c127SSebastian Grimberg 
968fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreateBlocked) {
96977d1c127SSebastian Grimberg     Ceed delegate;
97077d1c127SSebastian Grimberg 
97177d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
972ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedOriented");
973e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode,
97477d1c127SSebastian Grimberg                                                       offsets, orients, rstr));
97577d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
97677d1c127SSebastian Grimberg   }
97777d1c127SSebastian Grimberg 
97877d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
979e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
980ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
981ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
98277d1c127SSebastian Grimberg 
983e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
984e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_orients));
985e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
986e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOrients(orients, block_orients, num_block, num_elem, block_size, elem_size));
98777d1c127SSebastian Grimberg 
988fcbe8c06SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
989fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
99077d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
99177d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
99277d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
99377d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
99477d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
99577d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
9961203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
997e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
998e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
999fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_ORIENTED;
1000e7f679fcSJeremy L Thompson   CeedCall(
1001e7f679fcSJeremy L Thompson       ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, (const bool *)block_orients, NULL, *rstr));
10021c66c397SJeremy L Thompson   if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
100377d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
100477d1c127SSebastian Grimberg }
100577d1c127SSebastian Grimberg 
100677d1c127SSebastian Grimberg /**
1007ca94c3ddSJeremy L Thompson   @brief Create a blocked curl-oriented `CeedElemRestriction`, typically only used by backends
100877d1c127SSebastian Grimberg 
1009ca94c3ddSJeremy L Thompson   @param[in]  ceed         `Ceed` context used to create the `CeedElemRestriction`
1010ca94c3ddSJeremy L Thompson   @param[in]  num_elem     Number of elements described in the `offsets` array.
101177d1c127SSebastian Grimberg   @param[in]  elem_size    Size (number of unknowns) per element
1012e7f679fcSJeremy L Thompson   @param[in]  block_size   Number of elements in a block
101377d1c127SSebastian Grimberg   @param[in]  num_comp     Number of field components per interpolation node (1 for scalar fields)
1014fcbe8c06SSebastian Grimberg   @param[in]  comp_stride  Stride between components for the same L-vector "node".
1015ca94c3ddSJeremy L Thompson                              Data for node `i`, component `j`, element `k` can be found in the L-vector at index `offsets[i + k*elem_size] + j*comp_stride`.
1016fcbe8c06SSebastian Grimberg   @param[in]  l_size       The size of the L-vector.
1017fcbe8c06SSebastian Grimberg                              This vector may be larger than the elements and fields given by this restriction.
1018ca94c3ddSJeremy L Thompson   @param[in]  mem_type     Memory type of the `offsets` array, see @ref CeedMemType
1019ca94c3ddSJeremy L Thompson   @param[in]  copy_mode    Copy mode for the `offsets` array, see @ref CeedCopyMode
1020ca94c3ddSJeremy L Thompson   @param[in]  offsets      Array of shape `[num_elem, elem_size]`.
1021ca94c3ddSJeremy L Thompson                              Row `i` holds the ordered list of the offsets (into the input `CeedVector`) for the unknowns corresponding to element `i`, where `0 <= i < num_elem`.
1022ca94c3ddSJeremy L Thompson                              All offsets must be in the range `[0, l_size - 1]`.
1023ca94c3ddSJeremy L Thompson                              The backend will permute and pad this array to the desired  ordering for the blocksize, which is typically given by the backend.
1024ca94c3ddSJeremy L Thompson                              The default reordering is to interlace elements.
1025ca94c3ddSJeremy L Thompson   @param[in]  curl_orients Array of shape `[num_elem, 3 * elem_size]` representing a row-major tridiagonal matrix (`curl_orients[i * 3 * elem_size] = curl_orients[(i + 1) * 3 * elem_size - 1] = 0`, where `0 <= i < num_elem`) which is applied to the element unknowns upon restriction.
1026ca94c3ddSJeremy L Thompson                              This orientation matrix allows for pairs of face degrees of freedom on elements for \f$H(\mathrm{curl})\f$ spaces to be coupled in the element restriction  operation, which is a way to resolve face orientation issues for 3D meshes (https://dl.acm.org/doi/pdf/10.1145/3524456).
1027ca94c3ddSJeremy L Thompson                              Will also be permuted and padded similarly to offsets.
1028ca94c3ddSJeremy L Thompson   @param[out] rstr         Address of the variable where the newly created `CeedElemRestriction` will be stored
102977d1c127SSebastian Grimberg 
103077d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
103177d1c127SSebastian Grimberg 
103277d1c127SSebastian Grimberg   @ref Backend
103377d1c127SSebastian Grimberg  **/
1034e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp,
103577d1c127SSebastian Grimberg                                                  CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode,
10360c73c039SSebastian Grimberg                                                  const CeedInt *offsets, const CeedInt8 *curl_orients, CeedElemRestriction *rstr) {
1037e7f679fcSJeremy L Thompson   CeedInt8 *block_curl_orients;
10381c66c397SJeremy L Thompson   CeedInt  *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
103977d1c127SSebastian Grimberg 
1040fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreateBlocked) {
104177d1c127SSebastian Grimberg     Ceed delegate;
104277d1c127SSebastian Grimberg 
104377d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
1044ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedCurlOriented");
1045e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedCurlOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type,
1046e7f679fcSJeremy L Thompson                                                           copy_mode, offsets, curl_orients, rstr));
104777d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
104877d1c127SSebastian Grimberg   }
104977d1c127SSebastian Grimberg 
1050e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
105177d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
1052e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
1053ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
1054ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
105577d1c127SSebastian Grimberg 
1056e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
1057e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * 3 * elem_size, &block_curl_orients));
1058e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
1059e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadCurlOrients(curl_orients, block_curl_orients, num_block, num_elem, block_size, 3 * elem_size));
106077d1c127SSebastian Grimberg 
1061fcbe8c06SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
1062fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
106377d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
106477d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
106577d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
106677d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
106777d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
106877d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
10691203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1070e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
1071e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
1072fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_CURL_ORIENTED;
1073e7f679fcSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL,
1074e7f679fcSJeremy L Thompson                                               (const CeedInt8 *)block_curl_orients, *rstr));
10751c66c397SJeremy L Thompson   if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
107677d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
107777d1c127SSebastian Grimberg }
107877d1c127SSebastian Grimberg 
107977d1c127SSebastian Grimberg /**
1080ca94c3ddSJeremy L Thompson   @brief Create a blocked strided `CeedElemRestriction`, typically only used by backends
10817509a596Sjeremylt 
1082ca94c3ddSJeremy L Thompson   @param[in]  ceed        `Ceed` context used to create the `CeedElemRestriction`
1083ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described by the restriction
1084ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
1085e7f679fcSJeremy L Thompson   @param[in]  block_size  Number of elements in a block
1086ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
1087fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
1088fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
1089ca94c3ddSJeremy L Thompson   @param[in]  strides     Array for strides between `[nodes, components, elements]`.
1090ca94c3ddSJeremy L Thompson                             Data for node `i`, component `j`, element `k` can be found in the L-vector at index `i*strides[0] + j*strides[1] +k*strides[2]`.
1091ca94c3ddSJeremy L Thompson                             @ref CEED_STRIDES_BACKEND may be used for `CeedVector` ordered by the same `Ceed` backend.
1092ca94c3ddSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created `CeedElemRestriction` will be stored
10937509a596Sjeremylt 
10947509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
10957509a596Sjeremylt 
10967a982d89SJeremy L. Thompson   @ref User
10977509a596Sjeremylt **/
1098e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedSize l_size,
10998621c6c6SJeremy L Thompson                                             const CeedInt strides[3], CeedElemRestriction *rstr) {
1100e7f679fcSJeremy L Thompson   CeedInt num_block = (num_elem / block_size) + !!(num_elem % block_size);
11017509a596Sjeremylt 
11027509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
11037509a596Sjeremylt     Ceed delegate;
11046574a04fSJeremy L Thompson 
11052b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
1106ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedStrided");
1107e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, block_size, num_comp, l_size, strides, rstr));
1108e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
11097509a596Sjeremylt   }
11107509a596Sjeremylt 
1111e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
11126574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
1113e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
1114ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
111581670346SSebastian Grimberg   CeedCheck(l_size >= (CeedSize)num_elem * elem_size * num_comp, ceed, CEED_ERROR_DIMENSION,
111681670346SSebastian Grimberg             "L-vector size must be at least num_elem * elem_size * num_comp");
1117e022e1f8SJeremy L Thompson 
11182b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
1119db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
1120d1d35e2fSjeremylt   (*rstr)->ref_count  = 1;
1121d1d35e2fSjeremylt   (*rstr)->num_elem   = num_elem;
1122d1d35e2fSjeremylt   (*rstr)->elem_size  = elem_size;
1123d1d35e2fSjeremylt   (*rstr)->num_comp   = num_comp;
1124d1d35e2fSjeremylt   (*rstr)->l_size     = l_size;
11251203703bSJeremy L Thompson   (*rstr)->e_size     = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1126e7f679fcSJeremy L Thompson   (*rstr)->num_block  = num_block;
1127e7f679fcSJeremy L Thompson   (*rstr)->block_size = block_size;
1128fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type  = CEED_RESTRICTION_STRIDED;
11292b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
11302b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
1131fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
1132e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
11337509a596Sjeremylt }
11347509a596Sjeremylt 
11357509a596Sjeremylt /**
1136ca94c3ddSJeremy L Thompson   @brief Copy the pointer to a `CeedElemRestriction` and set @ref CeedElemRestrictionApply() implementation to use the unsigned version.
1137c17ec2beSJeremy L Thompson 
1138ca94c3ddSJeremy L Thompson   Both pointers should be destroyed with @ref CeedElemRestrictionDestroy().
1139c17ec2beSJeremy L Thompson 
1140ca94c3ddSJeremy L Thompson   @param[in]     rstr          `CeedElemRestriction` to create unsigned reference to
1141ca94c3ddSJeremy L Thompson   @param[in,out] rstr_unsigned Variable to store unsigned `CeedElemRestriction`
1142c17ec2beSJeremy L Thompson 
1143c17ec2beSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1144c17ec2beSJeremy L Thompson 
1145c17ec2beSJeremy L Thompson   @ref User
1146c17ec2beSJeremy L Thompson **/
1147c17ec2beSJeremy L Thompson int CeedElemRestrictionCreateUnsignedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unsigned) {
1148c17ec2beSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr_unsigned));
1149c17ec2beSJeremy L Thompson 
1150c17ec2beSJeremy L Thompson   // Copy old rstr
1151c17ec2beSJeremy L Thompson   memcpy(*rstr_unsigned, rstr, sizeof(struct CeedElemRestriction_private));
1152c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ceed = NULL;
1153c17ec2beSJeremy L Thompson   CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unsigned)->ceed));
1154c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ref_count = 1;
1155c17ec2beSJeremy L Thompson   (*rstr_unsigned)->strides   = NULL;
1156c17ec2beSJeremy L Thompson   if (rstr->strides) {
1157c17ec2beSJeremy L Thompson     CeedCall(CeedMalloc(3, &(*rstr_unsigned)->strides));
1158c17ec2beSJeremy L Thompson     for (CeedInt i = 0; i < 3; i++) (*rstr_unsigned)->strides[i] = rstr->strides[i];
1159c17ec2beSJeremy L Thompson   }
11607c1dbaffSSebastian Grimberg   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unsigned)->rstr_base));
1161c17ec2beSJeremy L Thompson 
1162c17ec2beSJeremy L Thompson   // Override Apply
1163c17ec2beSJeremy L Thompson   (*rstr_unsigned)->Apply = rstr->ApplyUnsigned;
1164c17ec2beSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1165c17ec2beSJeremy L Thompson }
1166c17ec2beSJeremy L Thompson 
1167c17ec2beSJeremy L Thompson /**
1168ca94c3ddSJeremy L Thompson   @brief Copy the pointer to a `CeedElemRestriction` and set @ref CeedElemRestrictionApply() implementation to use the unoriented version.
11697c1dbaffSSebastian Grimberg 
1170ca94c3ddSJeremy L Thompson   Both pointers should be destroyed with @ref CeedElemRestrictionDestroy().
11717c1dbaffSSebastian Grimberg 
1172ca94c3ddSJeremy L Thompson   @param[in]     rstr            `CeedElemRestriction` to create unoriented reference to
1173ca94c3ddSJeremy L Thompson   @param[in,out] rstr_unoriented Variable to store unoriented `CeedElemRestriction`
11747c1dbaffSSebastian Grimberg 
11757c1dbaffSSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
11767c1dbaffSSebastian Grimberg 
11777c1dbaffSSebastian Grimberg   @ref User
11787c1dbaffSSebastian Grimberg **/
11797c1dbaffSSebastian Grimberg int CeedElemRestrictionCreateUnorientedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unoriented) {
11807c1dbaffSSebastian Grimberg   CeedCall(CeedCalloc(1, rstr_unoriented));
11817c1dbaffSSebastian Grimberg 
11827c1dbaffSSebastian Grimberg   // Copy old rstr
11837c1dbaffSSebastian Grimberg   memcpy(*rstr_unoriented, rstr, sizeof(struct CeedElemRestriction_private));
11847c1dbaffSSebastian Grimberg   (*rstr_unoriented)->ceed = NULL;
11857c1dbaffSSebastian Grimberg   CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unoriented)->ceed));
11867c1dbaffSSebastian Grimberg   (*rstr_unoriented)->ref_count = 1;
11877c1dbaffSSebastian Grimberg   (*rstr_unoriented)->strides   = NULL;
11887c1dbaffSSebastian Grimberg   if (rstr->strides) {
11897c1dbaffSSebastian Grimberg     CeedCall(CeedMalloc(3, &(*rstr_unoriented)->strides));
11907c1dbaffSSebastian Grimberg     for (CeedInt i = 0; i < 3; i++) (*rstr_unoriented)->strides[i] = rstr->strides[i];
11917c1dbaffSSebastian Grimberg   }
11927c1dbaffSSebastian Grimberg   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unoriented)->rstr_base));
11937c1dbaffSSebastian Grimberg 
11947c1dbaffSSebastian Grimberg   // Override Apply
11957c1dbaffSSebastian Grimberg   (*rstr_unoriented)->Apply = rstr->ApplyUnoriented;
11967c1dbaffSSebastian Grimberg   return CEED_ERROR_SUCCESS;
11977c1dbaffSSebastian Grimberg }
11987c1dbaffSSebastian Grimberg 
11997c1dbaffSSebastian Grimberg /**
1200ca94c3ddSJeremy L Thompson   @brief Copy the pointer to a `CeedElemRestriction`.
12019fd66db6SSebastian Grimberg 
1202ca94c3ddSJeremy L Thompson   Both pointers should be destroyed with @ref CeedElemRestrictionDestroy().
12039560d06aSjeremylt 
1204ca94c3ddSJeremy L Thompson   Note: If the value of `*rstr_copy` passed into this function is non-`NULL`, then it is assumed that `*rstr_copy` is a pointer to a `CeedElemRestriction`.
1205ca94c3ddSJeremy L Thompson         This `CeedElemRestriction` will be destroyed if `*rstr_copy` is the only reference to this `CeedElemRestriction`.
1206ea61e9acSJeremy L Thompson 
1207ca94c3ddSJeremy L Thompson   @param[in]     rstr      `CeedElemRestriction` to copy reference to
1208ea61e9acSJeremy L Thompson   @param[in,out] rstr_copy Variable to store copied reference
12099560d06aSjeremylt 
12109560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
12119560d06aSjeremylt 
12129560d06aSjeremylt   @ref User
12139560d06aSjeremylt **/
12142b730f8bSJeremy L Thompson int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_copy) {
1215393ac2cdSJeremy L Thompson   if (rstr != CEED_ELEMRESTRICTION_NONE) CeedCall(CeedElemRestrictionReference(rstr));
12162b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionDestroy(rstr_copy));
12179560d06aSjeremylt   *rstr_copy = rstr;
12189560d06aSjeremylt   return CEED_ERROR_SUCCESS;
12199560d06aSjeremylt }
12209560d06aSjeremylt 
12219560d06aSjeremylt /**
1222ca94c3ddSJeremy L Thompson   @brief Create `CeedVector` associated with a `CeedElemRestriction`
1223b11c1e72Sjeremylt 
1224ca94c3ddSJeremy L Thompson   @param[in]  rstr  `CeedElemRestriction`
1225ca94c3ddSJeremy L Thompson   @param[out] l_vec The address of the L-vector to be created, or `NULL`
1226ca94c3ddSJeremy L Thompson   @param[out] e_vec The address of the E-vector to be created, or `NULL`
1227b11c1e72Sjeremylt 
1228b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1229dfdf5a53Sjeremylt 
12307a982d89SJeremy L. Thompson   @ref User
1231b11c1e72Sjeremylt **/
12322b730f8bSJeremy L Thompson int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, CeedVector *e_vec) {
1233d2643443SJeremy L Thompson   CeedSize e_size, l_size;
12341203703bSJeremy L Thompson   Ceed     ceed;
123548acf710SJeremy L Thompson 
12361203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
12371203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &l_size));
12381203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &e_size));
12391203703bSJeremy L Thompson   if (l_vec) CeedCall(CeedVectorCreate(ceed, l_size, l_vec));
12401203703bSJeremy L Thompson   if (e_vec) CeedCall(CeedVectorCreate(ceed, e_size, e_vec));
1241e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1242d7b241e6Sjeremylt }
1243d7b241e6Sjeremylt 
1244d7b241e6Sjeremylt /**
1245d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
1246d7b241e6Sjeremylt 
1247ca94c3ddSJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
1248ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1249ca94c3ddSJeremy L Thompson   @param[in]  u       Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE)
1250ca94c3ddSJeremy L Thompson   @param[out] ru      Output vector (of shape `[num_elem * elem_size]` when `t_mode` = @ref CEED_NOTRANSPOSE).
1251fcbe8c06SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
1252ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
1253b11c1e72Sjeremylt 
1254b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1255dfdf5a53Sjeremylt 
12567a982d89SJeremy L. Thompson   @ref User
1257b11c1e72Sjeremylt **/
12582b730f8bSJeremy L Thompson int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
1259701e7d35SJeremy L Thompson   CeedSize min_u_len, min_ru_len, len;
1260701e7d35SJeremy L Thompson   CeedInt  num_elem;
12611203703bSJeremy L Thompson   Ceed     ceed;
1262d7b241e6Sjeremylt 
12631203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
1264d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
1265701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &min_ru_len));
1266701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_u_len));
1267d7b241e6Sjeremylt   } else {
1268701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &min_u_len));
1269701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_ru_len));
1270d7b241e6Sjeremylt   }
1271701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(u, &len));
12721203703bSJeremy L Thompson   CeedCheck(min_u_len <= len, ceed, CEED_ERROR_DIMENSION,
1273701e7d35SJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_ru_len,
1274701e7d35SJeremy L Thompson             min_u_len);
1275701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(ru, &len));
12761203703bSJeremy L Thompson   CeedCheck(min_ru_len <= len, ceed, CEED_ERROR_DIMENSION,
1277701e7d35SJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_u_len,
1278701e7d35SJeremy L Thompson             min_ru_len);
1279701e7d35SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
1280701e7d35SJeremy L Thompson   if (num_elem > 0) CeedCall(rstr->Apply(rstr, t_mode, u, ru, request));
1281e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1282d7b241e6Sjeremylt }
1283d7b241e6Sjeremylt 
1284d7b241e6Sjeremylt /**
12853ac8f562SJeremy L Thompson   @brief Restrict an L-vector of points to a single element or apply its transpose
12863ac8f562SJeremy L Thompson 
1287ca94c3ddSJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
1288ca94c3ddSJeremy L Thompson   @param[in]  elem    Element number in range `[0, num_elem)`
12893ac8f562SJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1290ca94c3ddSJeremy L Thompson   @param[in]  u       Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE)
1291ca94c3ddSJeremy L Thompson   @param[out] ru      Output vector (of shape [`num_points * num_comp]` when `t_mode` = @ref CEED_NOTRANSPOSE).
12923ac8f562SJeremy L Thompson                         Ordering of the e-vector is decided by the backend.
12933ac8f562SJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
12943ac8f562SJeremy L Thompson 
12953ac8f562SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
12963ac8f562SJeremy L Thompson 
12973ac8f562SJeremy L Thompson   @ref User
12983ac8f562SJeremy L Thompson **/
129905fa913cSJeremy L Thompson int CeedElemRestrictionApplyAtPointsInElement(CeedElemRestriction rstr, CeedInt elem, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
13003ac8f562SJeremy L Thompson                                               CeedRequest *request) {
1301701e7d35SJeremy L Thompson   CeedSize min_u_len, min_ru_len, len;
1302701e7d35SJeremy L Thompson   CeedInt  num_elem;
13031203703bSJeremy L Thompson   Ceed     ceed;
13043ac8f562SJeremy L Thompson 
13051203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
13063ac8f562SJeremy L Thompson   if (t_mode == CEED_NOTRANSPOSE) {
1307701e7d35SJeremy L Thompson     CeedInt num_points, num_comp;
1308701e7d35SJeremy L Thompson 
1309701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_u_len));
1310701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, elem, &num_points));
1311701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
1312701e7d35SJeremy L Thompson     min_ru_len = (CeedSize)num_points * (CeedSize)num_comp;
13133ac8f562SJeremy L Thompson   } else {
1314701e7d35SJeremy L Thompson     CeedInt num_points, num_comp;
1315701e7d35SJeremy L Thompson 
1316701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, elem, &num_points));
1317701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
1318701e7d35SJeremy L Thompson     min_u_len = (CeedSize)num_points * (CeedSize)num_comp;
1319701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_ru_len));
13203ac8f562SJeremy L Thompson   }
1321701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(u, &len));
13221203703bSJeremy L Thompson   CeedCheck(min_u_len <= len, ceed, CEED_ERROR_DIMENSION,
13233ac8f562SJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT
13243ac8f562SJeremy L Thompson             ") for element %" CeedInt_FMT,
1325701e7d35SJeremy L Thompson             len, min_ru_len, min_u_len, elem);
1326701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(ru, &len));
13271203703bSJeremy L Thompson   CeedCheck(min_ru_len <= len, ceed, CEED_ERROR_DIMENSION,
13283ac8f562SJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT
13293ac8f562SJeremy L Thompson             ") for element %" CeedInt_FMT,
1330701e7d35SJeremy L Thompson             len, min_ru_len, min_u_len, elem);
1331701e7d35SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
13321203703bSJeremy L Thompson   CeedCheck(elem < num_elem, ceed, CEED_ERROR_DIMENSION,
1333701e7d35SJeremy L Thompson             "Cannot retrieve element %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", elem, elem, num_elem);
1334701e7d35SJeremy L Thompson   if (num_elem > 0) CeedCall(rstr->ApplyAtPointsInElement(rstr, elem, t_mode, u, ru, request));
13353ac8f562SJeremy L Thompson   return CEED_ERROR_SUCCESS;
13363ac8f562SJeremy L Thompson }
13373ac8f562SJeremy L Thompson 
13383ac8f562SJeremy L Thompson /**
1339d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
1340be9261b7Sjeremylt 
1341ca94c3ddSJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
1342ca94c3ddSJeremy L Thompson   @param[in]  block   Block number to restrict to/from, i.e. `block = 0` will handle elements `[0 : block_size]` and `block = 3` will handle elements `[3*block_size : 4*block_size]`
1343ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1344ca94c3ddSJeremy L Thompson   @param[in]  u       Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE)
1345ca94c3ddSJeremy L Thompson   @param[out] ru      Output vector (of shape `[block_size * elem_size]` when `t_mode` = @ref CEED_NOTRANSPOSE).
1346fcbe8c06SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
1347ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
1348be9261b7Sjeremylt 
1349be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
1350be9261b7Sjeremylt 
13517a982d89SJeremy L. Thompson   @ref Backend
1352be9261b7Sjeremylt **/
13532b730f8bSJeremy L Thompson int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
13542b730f8bSJeremy L Thompson                                   CeedRequest *request) {
1355701e7d35SJeremy L Thompson   CeedSize min_u_len, min_ru_len, len;
1356701e7d35SJeremy L Thompson   CeedInt  block_size, num_elem;
13571203703bSJeremy L Thompson   Ceed     ceed;
1358be9261b7Sjeremylt 
13591203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
13601203703bSJeremy L Thompson   CeedCheck(rstr->ApplyBlock, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionApplyBlock");
13616402da51SJeremy L Thompson 
1362701e7d35SJeremy L Thompson   CeedCall(CeedElemRestrictionGetBlockSize(rstr, &block_size));
1363d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
1364701e7d35SJeremy L Thompson     CeedInt elem_size, num_comp;
1365701e7d35SJeremy L Thompson 
1366701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetElementSize(rstr, &elem_size));
1367701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
1368701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_u_len));
1369701e7d35SJeremy L Thompson     min_ru_len = (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1370be9261b7Sjeremylt   } else {
1371701e7d35SJeremy L Thompson     CeedInt elem_size, num_comp;
1372701e7d35SJeremy L Thompson 
1373701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetElementSize(rstr, &elem_size));
1374701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
1375701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_ru_len));
1376701e7d35SJeremy L Thompson     min_u_len = (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1377be9261b7Sjeremylt   }
1378701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(u, &len));
13791203703bSJeremy L Thompson   CeedCheck(min_u_len == len, ceed, CEED_ERROR_DIMENSION,
1380701e7d35SJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_u_len,
1381701e7d35SJeremy L Thompson             min_ru_len);
1382701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(ru, &len));
13831203703bSJeremy L Thompson   CeedCheck(min_ru_len == len, ceed, CEED_ERROR_DIMENSION,
1384701e7d35SJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_ru_len,
1385701e7d35SJeremy L Thompson             min_u_len);
1386701e7d35SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
13871203703bSJeremy L Thompson   CeedCheck(block_size * block <= num_elem, ceed, CEED_ERROR_DIMENSION,
1388701e7d35SJeremy L Thompson             "Cannot retrieve block %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", block, block_size * block,
1389701e7d35SJeremy L Thompson             num_elem);
13902b730f8bSJeremy L Thompson   CeedCall(rstr->ApplyBlock(rstr, block, t_mode, u, ru, request));
1391e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1392be9261b7Sjeremylt }
1393be9261b7Sjeremylt 
1394be9261b7Sjeremylt /**
1395ca94c3ddSJeremy L Thompson   @brief Get the `Ceed` associated with a `CeedElemRestriction`
1396b7c9bbdaSJeremy L Thompson 
1397ca94c3ddSJeremy L Thompson   @param[in]  rstr `CeedElemRestriction`
1398ca94c3ddSJeremy L Thompson   @param[out] ceed Variable to store `Ceed`
1399b7c9bbdaSJeremy L Thompson 
1400b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1401b7c9bbdaSJeremy L Thompson 
1402b7c9bbdaSJeremy L Thompson   @ref Advanced
1403b7c9bbdaSJeremy L Thompson **/
1404b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
14056e536b99SJeremy L Thompson   *ceed = CeedElemRestrictionReturnCeed(rstr);
1406b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1407b7c9bbdaSJeremy L Thompson }
1408b7c9bbdaSJeremy L Thompson 
1409b7c9bbdaSJeremy L Thompson /**
14106e536b99SJeremy L Thompson   @brief Return the `Ceed` associated with a `CeedElemRestriction`
14116e536b99SJeremy L Thompson 
14126e536b99SJeremy L Thompson   @param[in]  rstr `CeedElemRestriction`
14136e536b99SJeremy L Thompson 
14146e536b99SJeremy L Thompson   @return `Ceed` associated with the `rstr`
14156e536b99SJeremy L Thompson 
14166e536b99SJeremy L Thompson   @ref Advanced
14176e536b99SJeremy L Thompson **/
14186e536b99SJeremy L Thompson Ceed CeedElemRestrictionReturnCeed(CeedElemRestriction rstr) { return rstr->ceed; }
14196e536b99SJeremy L Thompson 
14206e536b99SJeremy L Thompson /**
1421d979a051Sjeremylt   @brief Get the L-vector component stride
1422a681ae63Sjeremylt 
1423ca94c3ddSJeremy L Thompson   @param[in]  rstr        `CeedElemRestriction`
1424d1d35e2fSjeremylt   @param[out] comp_stride Variable to store component stride
1425a681ae63Sjeremylt 
1426a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1427a681ae63Sjeremylt 
1428b7c9bbdaSJeremy L Thompson   @ref Advanced
1429a681ae63Sjeremylt **/
14302b730f8bSJeremy L Thompson int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, CeedInt *comp_stride) {
1431d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
1432e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1433a681ae63Sjeremylt }
1434a681ae63Sjeremylt 
1435a681ae63Sjeremylt /**
1436ca94c3ddSJeremy L Thompson   @brief Get the total number of elements in the range of a `CeedElemRestriction`
1437a681ae63Sjeremylt 
1438ca94c3ddSJeremy L Thompson   @param[in] rstr      `CeedElemRestriction`
1439d1d35e2fSjeremylt   @param[out] num_elem Variable to store number of elements
1440a681ae63Sjeremylt 
1441a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1442a681ae63Sjeremylt 
1443b7c9bbdaSJeremy L Thompson   @ref Advanced
1444a681ae63Sjeremylt **/
14452b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, CeedInt *num_elem) {
1446d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
1447e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1448a681ae63Sjeremylt }
1449a681ae63Sjeremylt 
1450a681ae63Sjeremylt /**
1451ca94c3ddSJeremy L Thompson   @brief Get the size of elements in the `CeedElemRestriction`
1452a681ae63Sjeremylt 
1453ca94c3ddSJeremy L Thompson   @param[in]  rstr      `CeedElemRestriction`
1454d1d35e2fSjeremylt   @param[out] elem_size Variable to store size of elements
1455a681ae63Sjeremylt 
1456a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1457a681ae63Sjeremylt 
1458b7c9bbdaSJeremy L Thompson   @ref Advanced
1459a681ae63Sjeremylt **/
14602b730f8bSJeremy L Thompson int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, CeedInt *elem_size) {
1461d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
14622c7e7413SJeremy L Thompson   return CEED_ERROR_SUCCESS;
14632c7e7413SJeremy L Thompson }
14642c7e7413SJeremy L Thompson 
14652c7e7413SJeremy L Thompson /**
146607d5dec1SJeremy L Thompson 
1467ca94c3ddSJeremy L Thompson   @brief Get the number of points in the l-vector for a points `CeedElemRestriction`
146807d5dec1SJeremy L Thompson 
1469ca94c3ddSJeremy L Thompson   @param[in]  rstr       `CeedElemRestriction`
147007d5dec1SJeremy L Thompson   @param[out] num_points The number of points in the l-vector
147107d5dec1SJeremy L Thompson 
147207d5dec1SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
147307d5dec1SJeremy L Thompson 
1474c63574e3SJeremy L Thompson   @ref User
147507d5dec1SJeremy L Thompson **/
147607d5dec1SJeremy L Thompson int CeedElemRestrictionGetNumPoints(CeedElemRestriction rstr, CeedInt *num_points) {
14771203703bSJeremy L Thompson   CeedRestrictionType rstr_type;
147807d5dec1SJeremy L Thompson 
14791203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
14806e536b99SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
148107d5dec1SJeremy L Thompson             "Can only retrieve the number of points for a points CeedElemRestriction");
148207d5dec1SJeremy L Thompson 
148307d5dec1SJeremy L Thompson   *num_points = rstr->num_points;
148407d5dec1SJeremy L Thompson   return CEED_ERROR_SUCCESS;
148507d5dec1SJeremy L Thompson }
148607d5dec1SJeremy L Thompson 
148707d5dec1SJeremy L Thompson /**
148807d5dec1SJeremy L Thompson 
1489ca94c3ddSJeremy L Thompson   @brief Get the number of points in an element of a `CeedElemRestriction` at points
149007d5dec1SJeremy L Thompson 
1491ca94c3ddSJeremy L Thompson   @param[in]  rstr       `CeedElemRestriction`
149207d5dec1SJeremy L Thompson   @param[in]  elem       Index number of element to retrieve the number of points for
149307d5dec1SJeremy L Thompson   @param[out] num_points The number of points in the element at index elem
149407d5dec1SJeremy L Thompson 
149507d5dec1SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
149607d5dec1SJeremy L Thompson 
1497c63574e3SJeremy L Thompson   @ref User
149807d5dec1SJeremy L Thompson **/
149907d5dec1SJeremy L Thompson int CeedElemRestrictionGetNumPointsInElement(CeedElemRestriction rstr, CeedInt elem, CeedInt *num_points) {
15001203703bSJeremy L Thompson   CeedRestrictionType rstr_type;
150107d5dec1SJeremy L Thompson   const CeedInt      *offsets;
150207d5dec1SJeremy L Thompson 
15031203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
15046e536b99SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
150507d5dec1SJeremy L Thompson             "Can only retrieve the number of points for a points CeedElemRestriction");
150607d5dec1SJeremy L Thompson 
150707d5dec1SJeremy L Thompson   CeedCall(CeedElemRestrictionGetOffsets(rstr, CEED_MEM_HOST, &offsets));
150807d5dec1SJeremy L Thompson   *num_points = offsets[elem + 1] - offsets[elem];
150907d5dec1SJeremy L Thompson   CeedCall(CeedElemRestrictionRestoreOffsets(rstr, &offsets));
151007d5dec1SJeremy L Thompson   return CEED_ERROR_SUCCESS;
151107d5dec1SJeremy L Thompson }
151207d5dec1SJeremy L Thompson 
151307d5dec1SJeremy L Thompson /**
1514ca94c3ddSJeremy L Thompson   @brief Get the maximum number of points in an element for a `CeedElemRestriction` at points
15152c7e7413SJeremy L Thompson 
1516ca94c3ddSJeremy L Thompson   @param[in]  rstr       `CeedElemRestriction`
15172c7e7413SJeremy L Thompson   @param[out] max_points Variable to store size of elements
15182c7e7413SJeremy L Thompson 
15192c7e7413SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
15202c7e7413SJeremy L Thompson 
15212c7e7413SJeremy L Thompson   @ref Advanced
15222c7e7413SJeremy L Thompson **/
15232c7e7413SJeremy L Thompson int CeedElemRestrictionGetMaxPointsInElement(CeedElemRestriction rstr, CeedInt *max_points) {
15242c7e7413SJeremy L Thompson   CeedInt             num_elem;
15252c7e7413SJeremy L Thompson   CeedRestrictionType rstr_type;
15262c7e7413SJeremy L Thompson 
15272c7e7413SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
15286e536b99SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
15292c7e7413SJeremy L Thompson             "Cannot compute max points for a CeedElemRestriction that does not use points");
15302c7e7413SJeremy L Thompson 
15312c7e7413SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
15322c7e7413SJeremy L Thompson   *max_points = 0;
15332c7e7413SJeremy L Thompson   for (CeedInt e = 0; e < num_elem; e++) {
15342c7e7413SJeremy L Thompson     CeedInt num_points;
15352c7e7413SJeremy L Thompson 
15362c7e7413SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, e, &num_points));
15372c7e7413SJeremy L Thompson     *max_points = CeedIntMax(num_points, *max_points);
15382c7e7413SJeremy L Thompson   }
1539e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1540a681ae63Sjeremylt }
1541a681ae63Sjeremylt 
1542a681ae63Sjeremylt /**
1543ca94c3ddSJeremy L Thompson   @brief Get the size of the l-vector for a `CeedElemRestriction`
1544a681ae63Sjeremylt 
1545ca94c3ddSJeremy L Thompson   @param[in]  rstr   `CeedElemRestriction`
1546701e7d35SJeremy L Thompson   @param[out] l_size Variable to store l-vector size
1547a681ae63Sjeremylt 
1548a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1549a681ae63Sjeremylt 
1550b7c9bbdaSJeremy L Thompson   @ref Advanced
1551a681ae63Sjeremylt **/
15522b730f8bSJeremy L Thompson int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, CeedSize *l_size) {
1553d1d35e2fSjeremylt   *l_size = rstr->l_size;
1554e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1555a681ae63Sjeremylt }
1556a681ae63Sjeremylt 
1557a681ae63Sjeremylt /**
1558701e7d35SJeremy L Thompson   @brief Get the size of the e-vector for a `CeedElemRestriction`
1559701e7d35SJeremy L Thompson 
1560701e7d35SJeremy L Thompson   @param[in]  rstr   `CeedElemRestriction`
1561701e7d35SJeremy L Thompson   @param[out] e_size Variable to store e-vector size
1562701e7d35SJeremy L Thompson 
1563701e7d35SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1564701e7d35SJeremy L Thompson 
1565701e7d35SJeremy L Thompson   @ref Advanced
1566701e7d35SJeremy L Thompson **/
1567701e7d35SJeremy L Thompson int CeedElemRestrictionGetEVectorSize(CeedElemRestriction rstr, CeedSize *e_size) {
1568701e7d35SJeremy L Thompson   *e_size = rstr->e_size;
1569701e7d35SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1570701e7d35SJeremy L Thompson }
1571701e7d35SJeremy L Thompson 
1572701e7d35SJeremy L Thompson /**
1573ca94c3ddSJeremy L Thompson   @brief Get the number of components in the elements of a `CeedElemRestriction`
1574a681ae63Sjeremylt 
1575ca94c3ddSJeremy L Thompson   @param[in]  rstr     `CeedElemRestriction`
1576d1d35e2fSjeremylt   @param[out] num_comp Variable to store number of components
1577a681ae63Sjeremylt 
1578a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1579a681ae63Sjeremylt 
1580b7c9bbdaSJeremy L Thompson   @ref Advanced
1581a681ae63Sjeremylt **/
15822b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, CeedInt *num_comp) {
1583d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
1584e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1585a681ae63Sjeremylt }
1586a681ae63Sjeremylt 
1587a681ae63Sjeremylt /**
1588ca94c3ddSJeremy L Thompson   @brief Get the number of blocks in a `CeedElemRestriction`
1589a681ae63Sjeremylt 
1590ca94c3ddSJeremy L Thompson   @param[in]  rstr      `CeedElemRestriction`
1591d1d35e2fSjeremylt   @param[out] num_block Variable to store number of blocks
1592a681ae63Sjeremylt 
1593a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1594a681ae63Sjeremylt 
1595b7c9bbdaSJeremy L Thompson   @ref Advanced
1596a681ae63Sjeremylt **/
15972b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, CeedInt *num_block) {
1598e7f679fcSJeremy L Thompson   *num_block = rstr->num_block;
1599e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1600a681ae63Sjeremylt }
1601a681ae63Sjeremylt 
1602a681ae63Sjeremylt /**
1603ca94c3ddSJeremy L Thompson   @brief Get the size of blocks in the `CeedElemRestriction`
1604a681ae63Sjeremylt 
1605ca94c3ddSJeremy L Thompson   @param[in]  rstr       `CeedElemRestriction`
1606e7f679fcSJeremy L Thompson   @param[out] block_size Variable to store size of blocks
1607a681ae63Sjeremylt 
1608a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1609a681ae63Sjeremylt 
1610b7c9bbdaSJeremy L Thompson   @ref Advanced
1611a681ae63Sjeremylt **/
1612e7f679fcSJeremy L Thompson int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, CeedInt *block_size) {
1613e7f679fcSJeremy L Thompson   *block_size = rstr->block_size;
1614e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1615a681ae63Sjeremylt }
1616a681ae63Sjeremylt 
1617a681ae63Sjeremylt /**
1618ca94c3ddSJeremy L Thompson   @brief Get the multiplicity of nodes in a `CeedElemRestriction`
16191469ee4dSjeremylt 
1620ca94c3ddSJeremy L Thompson   @param[in]  rstr `CeedElemRestriction`
1621ca94c3ddSJeremy L Thompson   @param[out] mult Vector to store multiplicity (of size `l_size`)
16221469ee4dSjeremylt 
16231469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
16241469ee4dSjeremylt 
16257a982d89SJeremy L. Thompson   @ref User
16261469ee4dSjeremylt **/
16272b730f8bSJeremy L Thompson int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, CeedVector mult) {
1628d1d35e2fSjeremylt   CeedVector e_vec;
16291469ee4dSjeremylt 
163025509ebbSRezgar Shakeri   // Create e_vec to hold intermediate computation in E^T (E 1)
16312b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionCreateVector(rstr, NULL, &e_vec));
16321469ee4dSjeremylt 
163325509ebbSRezgar Shakeri   // Compute e_vec = E * 1
16342b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 1.0));
16352b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, CEED_REQUEST_IMMEDIATE));
163625509ebbSRezgar Shakeri   // Compute multiplicity, mult = E^T * e_vec = E^T (E 1)
16372b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 0.0));
16382b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, CEED_REQUEST_IMMEDIATE));
16391469ee4dSjeremylt   // Cleanup
16402b730f8bSJeremy L Thompson   CeedCall(CeedVectorDestroy(&e_vec));
1641e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
16421469ee4dSjeremylt }
16431469ee4dSjeremylt 
16441469ee4dSjeremylt /**
1645ca94c3ddSJeremy L Thompson   @brief View a `CeedElemRestriction`
1646f02ca4a2SJed Brown 
1647ca94c3ddSJeremy L Thompson   @param[in] rstr   `CeedElemRestriction` to view
1648ca94c3ddSJeremy L Thompson   @param[in] stream Stream to write; typically `stdout` or a file
1649f02ca4a2SJed Brown 
1650f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
1651f02ca4a2SJed Brown 
16527a982d89SJeremy L. Thompson   @ref User
1653f02ca4a2SJed Brown **/
1654f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
16550930e4e7SJeremy L Thompson   CeedRestrictionType rstr_type;
16560930e4e7SJeremy L Thompson 
16570930e4e7SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
16580930e4e7SJeremy L Thompson   if (rstr_type == CEED_RESTRICTION_POINTS) {
16590930e4e7SJeremy L Thompson     CeedInt max_points;
16600930e4e7SJeremy L Thompson 
16610930e4e7SJeremy L Thompson     CeedCall(CeedElemRestrictionGetMaxPointsInElement(rstr, &max_points));
16620930e4e7SJeremy L Thompson     fprintf(stream,
1663249f8407SJeremy L Thompson             "CeedElemRestriction at points from (%" CeedSize_FMT ", %" CeedInt_FMT ") to %" CeedInt_FMT " elements with a maximum of %" CeedInt_FMT
16640930e4e7SJeremy L Thompson             " points on an element\n",
16650930e4e7SJeremy L Thompson             rstr->l_size, rstr->num_comp, rstr->num_elem, max_points);
16660930e4e7SJeremy L Thompson   } else {
1667249f8407SJeremy L Thompson     char strides_str[500];
16681c66c397SJeremy L Thompson 
16692b730f8bSJeremy L Thompson     if (rstr->strides) {
1670249f8407SJeremy L Thompson       sprintf(strides_str, "[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "]", rstr->strides[0], rstr->strides[1], rstr->strides[2]);
16712b730f8bSJeremy L Thompson     } else {
1672249f8407SJeremy L Thompson       sprintf(strides_str, "%" CeedInt_FMT, rstr->comp_stride);
16732b730f8bSJeremy L Thompson     }
1674249f8407SJeremy L Thompson     fprintf(stream,
1675249f8407SJeremy L Thompson             "%sCeedElemRestriction from (%" CeedSize_FMT ", %" CeedInt_FMT ") to %" CeedInt_FMT " elements with %" CeedInt_FMT
1676249f8407SJeremy L Thompson             " nodes each and %s %s\n",
1677e7f679fcSJeremy L Thompson             rstr->block_size > 1 ? "Blocked " : "", rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
1678249f8407SJeremy L Thompson             rstr->strides ? "strides" : "component stride", strides_str);
16790930e4e7SJeremy L Thompson   }
1680e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1681f02ca4a2SJed Brown }
1682f02ca4a2SJed Brown 
1683f02ca4a2SJed Brown /**
1684ca94c3ddSJeremy L Thompson   @brief Destroy a `CeedElemRestriction`
1685b11c1e72Sjeremylt 
1686ca94c3ddSJeremy L Thompson   @param[in,out] rstr `CeedElemRestriction` to destroy
1687b11c1e72Sjeremylt 
1688b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1689dfdf5a53Sjeremylt 
16907a982d89SJeremy L. Thompson   @ref User
1691b11c1e72Sjeremylt **/
16924ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
1693393ac2cdSJeremy L Thompson   if (!*rstr || *rstr == CEED_ELEMRESTRICTION_NONE || --(*rstr)->ref_count > 0) {
1694ad6481ceSJeremy L Thompson     *rstr = NULL;
1695ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
1696ad6481ceSJeremy L Thompson   }
16976574a04fSJeremy L Thompson   CeedCheck((*rstr)->num_readers == 0, (*rstr)->ceed, CEED_ERROR_ACCESS,
16986574a04fSJeremy L Thompson             "Cannot destroy CeedElemRestriction, a process has read access to the offset data");
1699c17ec2beSJeremy L Thompson 
1700c17ec2beSJeremy L Thompson   // Only destroy backend data once between rstr and unsigned copy
17017c1dbaffSSebastian Grimberg   if ((*rstr)->rstr_base) CeedCall(CeedElemRestrictionDestroy(&(*rstr)->rstr_base));
1702c17ec2beSJeremy L Thompson   else if ((*rstr)->Destroy) CeedCall((*rstr)->Destroy(*rstr));
1703c17ec2beSJeremy L Thompson 
17042b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*rstr)->strides));
17052b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*rstr)->ceed));
17062b730f8bSJeremy L Thompson   CeedCall(CeedFree(rstr));
1707e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1708d7b241e6Sjeremylt }
1709d7b241e6Sjeremylt 
1710d7b241e6Sjeremylt /// @}
1711