xref: /libCEED/interface/ceed-elemrestriction.c (revision 1203703b5dc87b4acbe66c9a27384ca8ad07798d)
13d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
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;
167*1203703bSJeremy L Thompson   Ceed    ceed;
168*1203703bSJeremy L Thompson 
169*1203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr_a, &ceed));
17048acf710SJeremy L Thompson 
17148acf710SJeremy L Thompson   // Cannot compare non-points restrictions
172*1203703bSJeremy L Thompson   CeedCheck(rstr_a->rstr_type == CEED_RESTRICTION_POINTS, ceed, CEED_ERROR_UNSUPPORTED, "First CeedElemRestriction must be AtPoints");
173*1203703bSJeremy 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]) {
207*1203703bSJeremy L Thompson   Ceed ceed;
208*1203703bSJeremy L Thompson 
209*1203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
210*1203703bSJeremy L Thompson   CeedCheck(rstr->strides, ceed, CEED_ERROR_MINOR, "CeedElemRestriction has no stride data");
21156c48462SJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) strides[i] = rstr->strides[i];
212e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2137a982d89SJeremy L. Thompson }
2147a982d89SJeremy L. Thompson 
2157a982d89SJeremy L. Thompson /**
216ca94c3ddSJeremy L Thompson   @brief Get the backend stride status of a `CeedElemRestriction`
21777d1c127SSebastian Grimberg 
218ca94c3ddSJeremy L Thompson   @param[in]  rstr                 `CeedElemRestriction`
21977d1c127SSebastian Grimberg   @param[out] has_backend_strides  Variable to store stride status
22077d1c127SSebastian Grimberg 
22177d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
22277d1c127SSebastian Grimberg 
22377d1c127SSebastian Grimberg   @ref Backend
22477d1c127SSebastian Grimberg **/
22577d1c127SSebastian Grimberg int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, bool *has_backend_strides) {
226*1203703bSJeremy L Thompson   Ceed ceed;
227*1203703bSJeremy L Thompson 
228*1203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
229*1203703bSJeremy L Thompson   CeedCheck(rstr->strides, ceed, CEED_ERROR_MINOR, "CeedElemRestriction has no stride data");
23077d1c127SSebastian Grimberg   *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
23177d1c127SSebastian Grimberg                           (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
23277d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
23377d1c127SSebastian Grimberg }
23477d1c127SSebastian Grimberg 
23577d1c127SSebastian Grimberg /**
236ca94c3ddSJeremy L Thompson   @brief Get read-only access to a `CeedElemRestriction` offsets array by @ref CeedMemType
237bd33150aSjeremylt 
238ca94c3ddSJeremy L Thompson   @param[in]  rstr     `CeedElemRestriction` to retrieve offsets
239fcbe8c06SSebastian Grimberg   @param[in]  mem_type Memory type on which to access the array.
240fcbe8c06SSebastian Grimberg                          If the backend uses a different memory type, this will perform a copy (possibly cached).
241ca94c3ddSJeremy L Thompson   @param[out] offsets  Array on memory type `mem_type`
242bd33150aSjeremylt 
243bd33150aSjeremylt   @return An error code: 0 - success, otherwise - failure
244bd33150aSjeremylt 
245bd33150aSjeremylt   @ref User
246bd33150aSjeremylt **/
2472b730f8bSJeremy L Thompson int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) {
2487c1dbaffSSebastian Grimberg   if (rstr->rstr_base) {
2497c1dbaffSSebastian Grimberg     CeedCall(CeedElemRestrictionGetOffsets(rstr->rstr_base, mem_type, offsets));
250c17ec2beSJeremy L Thompson   } else {
251*1203703bSJeremy L Thompson     Ceed ceed;
252*1203703bSJeremy L Thompson 
253*1203703bSJeremy L Thompson     CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
254*1203703bSJeremy L Thompson     CeedCheck(rstr->GetOffsets, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support CeedElemRestrictionGetOffsets");
2552b730f8bSJeremy L Thompson     CeedCall(rstr->GetOffsets(rstr, mem_type, offsets));
256d1d35e2fSjeremylt     rstr->num_readers++;
257c17ec2beSJeremy L Thompson   }
258e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
259430758c8SJeremy L Thompson }
260430758c8SJeremy L Thompson 
261430758c8SJeremy L Thompson /**
262ca94c3ddSJeremy L Thompson   @brief Restore an offsets array obtained using @ref CeedElemRestrictionGetOffsets()
263430758c8SJeremy L Thompson 
264ca94c3ddSJeremy L Thompson   @param[in] rstr    `CeedElemRestriction` to restore
265ea61e9acSJeremy L Thompson   @param[in] offsets Array of offset data
266430758c8SJeremy L Thompson 
267430758c8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
268430758c8SJeremy L Thompson 
269430758c8SJeremy L Thompson   @ref User
270430758c8SJeremy L Thompson **/
2712b730f8bSJeremy L Thompson int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr, const CeedInt **offsets) {
2727c1dbaffSSebastian Grimberg   if (rstr->rstr_base) {
2737c1dbaffSSebastian Grimberg     CeedCall(CeedElemRestrictionRestoreOffsets(rstr->rstr_base, offsets));
274c17ec2beSJeremy L Thompson   } else {
275430758c8SJeremy L Thompson     *offsets = NULL;
276d1d35e2fSjeremylt     rstr->num_readers--;
277c17ec2beSJeremy L Thompson   }
278e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
279bd33150aSjeremylt }
280bd33150aSjeremylt 
281bd33150aSjeremylt /**
282ca94c3ddSJeremy L Thompson   @brief Get read-only access to a `CeedElemRestriction` orientations array by @ref CeedMemType
2833ac43b2cSJeremy L Thompson 
284ca94c3ddSJeremy L Thompson   @param[in]  rstr     `CeedElemRestriction` to retrieve orientations
285fcbe8c06SSebastian Grimberg   @param[in]  mem_type Memory type on which to access the array.
286fcbe8c06SSebastian Grimberg                          If the backend uses a different memory type, this will perform a copy (possibly cached).
287ca94c3ddSJeremy L Thompson   @param[out] orients  Array on memory type `mem_type`
2883ac43b2cSJeremy L Thompson 
2893ac43b2cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2903ac43b2cSJeremy L Thompson 
29177d1c127SSebastian Grimberg   @ref User
2923ac43b2cSJeremy L Thompson **/
29377d1c127SSebastian Grimberg int CeedElemRestrictionGetOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const bool **orients) {
294*1203703bSJeremy L Thompson   Ceed ceed;
295*1203703bSJeremy L Thompson 
296*1203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
297*1203703bSJeremy L Thompson   CeedCheck(rstr->GetOrientations, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support CeedElemRestrictionGetOrientations");
29877d1c127SSebastian Grimberg   CeedCall(rstr->GetOrientations(rstr, mem_type, orients));
29977d1c127SSebastian Grimberg   rstr->num_readers++;
300e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3013ac43b2cSJeremy L Thompson }
3023ac43b2cSJeremy L Thompson 
3033ac43b2cSJeremy L Thompson /**
304ca94c3ddSJeremy L Thompson   @brief Restore an orientations array obtained using @ref CeedElemRestrictionGetOrientations()
305b435c5a6Srezgarshakeri 
306ca94c3ddSJeremy L Thompson   @param[in] rstr    `CeedElemRestriction` to restore
30777d1c127SSebastian Grimberg   @param[in] orients Array of orientation data
308b435c5a6Srezgarshakeri 
309b435c5a6Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
310b435c5a6Srezgarshakeri 
31177d1c127SSebastian Grimberg   @ref User
312b435c5a6Srezgarshakeri **/
31377d1c127SSebastian Grimberg int CeedElemRestrictionRestoreOrientations(CeedElemRestriction rstr, const bool **orients) {
31477d1c127SSebastian Grimberg   *orients = NULL;
31577d1c127SSebastian Grimberg   rstr->num_readers--;
316b435c5a6Srezgarshakeri   return CEED_ERROR_SUCCESS;
317b435c5a6Srezgarshakeri }
318b435c5a6Srezgarshakeri 
319b435c5a6Srezgarshakeri /**
320ca94c3ddSJeremy L Thompson   @brief Get read-only access to a `CeedElemRestriction` curl-conforming orientations array by @ref CeedMemType
3217a982d89SJeremy L. Thompson 
322ca94c3ddSJeremy L Thompson   @param[in]  rstr         `CeedElemRestriction` to retrieve curl-conforming orientations
323fcbe8c06SSebastian Grimberg   @param[in]  mem_type     Memory type on which to access the array.
324fcbe8c06SSebastian Grimberg                              If the backend uses a different memory type, this will perform a copy (possibly cached).
325ca94c3ddSJeremy L Thompson   @param[out] curl_orients Array on memory type `mem_type`
3267a982d89SJeremy L. Thompson 
3277a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3287a982d89SJeremy L. Thompson 
32977d1c127SSebastian Grimberg   @ref User
3307a982d89SJeremy L. Thompson **/
3310c73c039SSebastian Grimberg int CeedElemRestrictionGetCurlOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt8 **curl_orients) {
332*1203703bSJeremy L Thompson   Ceed ceed;
333*1203703bSJeremy L Thompson 
334*1203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
335*1203703bSJeremy L Thompson   CeedCheck(rstr->GetCurlOrientations, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support CeedElemRestrictionGetCurlOrientations");
33677d1c127SSebastian Grimberg   CeedCall(rstr->GetCurlOrientations(rstr, mem_type, curl_orients));
33777d1c127SSebastian Grimberg   rstr->num_readers++;
33877d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
33977d1c127SSebastian Grimberg }
34077d1c127SSebastian Grimberg 
34177d1c127SSebastian Grimberg /**
342ca94c3ddSJeremy L Thompson   @brief Restore an orientations array obtained using @ref CeedElemRestrictionGetCurlOrientations()
34377d1c127SSebastian Grimberg 
344ca94c3ddSJeremy L Thompson   @param[in] rstr         `CeedElemRestriction` to restore
34577d1c127SSebastian Grimberg   @param[in] curl_orients Array of orientation data
34677d1c127SSebastian Grimberg 
34777d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
34877d1c127SSebastian Grimberg 
34977d1c127SSebastian Grimberg   @ref User
35077d1c127SSebastian Grimberg **/
3510c73c039SSebastian Grimberg int CeedElemRestrictionRestoreCurlOrientations(CeedElemRestriction rstr, const CeedInt8 **curl_orients) {
35277d1c127SSebastian Grimberg   *curl_orients = NULL;
35377d1c127SSebastian Grimberg   rstr->num_readers--;
354e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3557a982d89SJeremy L. Thompson }
3567a982d89SJeremy L. Thompson 
3577a982d89SJeremy L. Thompson /**
35849fd234cSJeremy L Thompson 
35922eb1385SJeremy L Thompson   @brief Get the L-vector layout of a strided `CeedElemRestriction`
36022eb1385SJeremy L Thompson 
36122eb1385SJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
36222eb1385SJeremy L Thompson   @param[out] layout  Variable to store layout array, stored as `[nodes, components, elements]`.
36322eb1385SJeremy 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]`.
36422eb1385SJeremy L Thompson 
36522eb1385SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
36622eb1385SJeremy L Thompson 
36722eb1385SJeremy L Thompson   @ref Backend
36822eb1385SJeremy L Thompson **/
36956c48462SJeremy L Thompson int CeedElemRestrictionGetLLayout(CeedElemRestriction rstr, CeedInt layout[3]) {
37022eb1385SJeremy L Thompson   bool                has_backend_strides;
37122eb1385SJeremy L Thompson   CeedRestrictionType rstr_type;
372*1203703bSJeremy L Thompson   Ceed                ceed;
37322eb1385SJeremy L Thompson 
374*1203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
37522eb1385SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
376*1203703bSJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_STRIDED, ceed, CEED_ERROR_MINOR, "Only strided CeedElemRestriction have strided L-vector layout");
37722eb1385SJeremy L Thompson   CeedCall(CeedElemRestrictionHasBackendStrides(rstr, &has_backend_strides));
37822eb1385SJeremy L Thompson   if (has_backend_strides) {
379*1203703bSJeremy L Thompson     CeedCheck(rstr->l_layout[0], ceed, CEED_ERROR_MINOR, "CeedElemRestriction has no L-vector layout data");
38056c48462SJeremy L Thompson     for (CeedInt i = 0; i < 3; i++) layout[i] = rstr->l_layout[i];
38122eb1385SJeremy L Thompson   } else {
38222eb1385SJeremy L Thompson     CeedCall(CeedElemRestrictionGetStrides(rstr, layout));
38322eb1385SJeremy L Thompson   }
38422eb1385SJeremy L Thompson   return CEED_ERROR_SUCCESS;
38522eb1385SJeremy L Thompson }
38622eb1385SJeremy L Thompson 
38722eb1385SJeremy L Thompson /**
38822eb1385SJeremy L Thompson 
38922eb1385SJeremy L Thompson   @brief Set the L-vector layout of a strided `CeedElemRestriction`
39022eb1385SJeremy L Thompson 
39122eb1385SJeremy L Thompson   @param[in] rstr   `CeedElemRestriction`
39222eb1385SJeremy L Thompson   @param[in] layout Variable to containing layout array, stored as `[nodes, components, elements]`.
39322eb1385SJeremy 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]`.
39422eb1385SJeremy L Thompson 
39522eb1385SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
39622eb1385SJeremy L Thompson 
39722eb1385SJeremy L Thompson   @ref Backend
39822eb1385SJeremy L Thompson **/
39922eb1385SJeremy L Thompson int CeedElemRestrictionSetLLayout(CeedElemRestriction rstr, CeedInt layout[3]) {
40022eb1385SJeremy L Thompson   CeedRestrictionType rstr_type;
401*1203703bSJeremy L Thompson   Ceed                ceed;
40222eb1385SJeremy L Thompson 
403*1203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
40422eb1385SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
405*1203703bSJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_STRIDED, ceed, CEED_ERROR_MINOR, "Only strided CeedElemRestriction have strided L-vector layout");
40622eb1385SJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) rstr->l_layout[i] = layout[i];
40722eb1385SJeremy L Thompson   return CEED_ERROR_SUCCESS;
40822eb1385SJeremy L Thompson }
40922eb1385SJeremy L Thompson 
41022eb1385SJeremy L Thompson /**
41122eb1385SJeremy L Thompson 
412ca94c3ddSJeremy L Thompson   @brief Get the E-vector layout of a `CeedElemRestriction`
41349fd234cSJeremy L Thompson 
414ca94c3ddSJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
415ca94c3ddSJeremy L Thompson   @param[out] layout  Variable to store layout array, stored as `[nodes, components, elements]`.
416ca94c3ddSJeremy 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]`.
41749fd234cSJeremy L Thompson 
41849fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
41949fd234cSJeremy L Thompson 
42049fd234cSJeremy L Thompson   @ref Backend
42149fd234cSJeremy L Thompson **/
42256c48462SJeremy L Thompson int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
423*1203703bSJeremy L Thompson   Ceed ceed;
424*1203703bSJeremy L Thompson 
425*1203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
426*1203703bSJeremy L Thompson   CeedCheck(rstr->e_layout[0], ceed, CEED_ERROR_MINOR, "CeedElemRestriction has no E-vector layout data");
42756c48462SJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) layout[i] = rstr->e_layout[i];
428e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
42949fd234cSJeremy L Thompson }
43049fd234cSJeremy L Thompson 
43149fd234cSJeremy L Thompson /**
43249fd234cSJeremy L Thompson 
433ca94c3ddSJeremy L Thompson   @brief Set the E-vector layout of a `CeedElemRestriction`
43449fd234cSJeremy L Thompson 
435ca94c3ddSJeremy L Thompson   @param[in] rstr   `CeedElemRestriction`
436ca94c3ddSJeremy L Thompson   @param[in] layout Variable to containing layout array, stored as `[nodes, components, elements]`.
437ca94c3ddSJeremy 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]`.
43849fd234cSJeremy L Thompson 
43949fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
44049fd234cSJeremy L Thompson 
44149fd234cSJeremy L Thompson   @ref Backend
44249fd234cSJeremy L Thompson **/
4432b730f8bSJeremy L Thompson int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
44422eb1385SJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) rstr->e_layout[i] = layout[i];
445e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
44649fd234cSJeremy L Thompson }
44749fd234cSJeremy L Thompson 
44849fd234cSJeremy L Thompson /**
449ca94c3ddSJeremy L Thompson   @brief Get the backend data of a `CeedElemRestriction`
4507a982d89SJeremy L. Thompson 
451ca94c3ddSJeremy L Thompson   @param[in]  rstr `CeedElemRestriction`
4527a982d89SJeremy L. Thompson   @param[out] data Variable to store data
4537a982d89SJeremy L. Thompson 
4547a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4557a982d89SJeremy L. Thompson 
4567a982d89SJeremy L. Thompson   @ref Backend
4577a982d89SJeremy L. Thompson **/
458777ff853SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) {
459777ff853SJeremy L Thompson   *(void **)data = rstr->data;
460e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4617a982d89SJeremy L. Thompson }
4627a982d89SJeremy L. Thompson 
4637a982d89SJeremy L. Thompson /**
464ca94c3ddSJeremy L Thompson   @brief Set the backend data of a `CeedElemRestriction`
4657a982d89SJeremy L. Thompson 
466ca94c3ddSJeremy L Thompson   @param[in,out] rstr `CeedElemRestriction`
467ea61e9acSJeremy L Thompson   @param[in]     data Data to set
4687a982d89SJeremy L. Thompson 
4697a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4707a982d89SJeremy L. Thompson 
4717a982d89SJeremy L. Thompson   @ref Backend
4727a982d89SJeremy L. Thompson **/
473777ff853SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) {
474777ff853SJeremy L Thompson   rstr->data = data;
475e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4767a982d89SJeremy L. Thompson }
4777a982d89SJeremy L. Thompson 
47834359f16Sjeremylt /**
479ca94c3ddSJeremy L Thompson   @brief Increment the reference counter for a `CeedElemRestriction`
48034359f16Sjeremylt 
481ca94c3ddSJeremy L Thompson   @param[in,out] rstr `CeedElemRestriction` to increment the reference counter
48234359f16Sjeremylt 
48334359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
48434359f16Sjeremylt 
48534359f16Sjeremylt   @ref Backend
48634359f16Sjeremylt **/
4879560d06aSjeremylt int CeedElemRestrictionReference(CeedElemRestriction rstr) {
48834359f16Sjeremylt   rstr->ref_count++;
48934359f16Sjeremylt   return CEED_ERROR_SUCCESS;
49034359f16Sjeremylt }
49134359f16Sjeremylt 
4926e15d496SJeremy L Thompson /**
493ca94c3ddSJeremy L Thompson   @brief Estimate number of FLOPs required to apply `CeedElemRestriction` in `t_mode`
4946e15d496SJeremy L Thompson 
495ca94c3ddSJeremy L Thompson   @param[in]  rstr   `CeedElemRestriction` to estimate FLOPs for
496ea61e9acSJeremy L Thompson   @param[in]  t_mode Apply restriction or transpose
497ea61e9acSJeremy L Thompson   @param[out] flops  Address of variable to hold FLOPs estimate
4986e15d496SJeremy L Thompson 
4996e15d496SJeremy L Thompson   @ref Backend
5006e15d496SJeremy L Thompson **/
5012b730f8bSJeremy L Thompson int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedSize *flops) {
502*1203703bSJeremy L Thompson   CeedSize            e_size, scale = 0;
50389edb9e3SSebastian Grimberg   CeedRestrictionType rstr_type;
5041c66c397SJeremy L Thompson 
505*1203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &e_size));
50689edb9e3SSebastian Grimberg   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
50777d1c127SSebastian Grimberg   if (t_mode == CEED_TRANSPOSE) {
50889edb9e3SSebastian Grimberg     switch (rstr_type) {
5093ac8f562SJeremy L Thompson       case CEED_RESTRICTION_POINTS:
5103ac8f562SJeremy L Thompson         scale = 0;
5113ac8f562SJeremy L Thompson         break;
51289edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STRIDED:
51389edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STANDARD:
51477d1c127SSebastian Grimberg         scale = 1;
51589edb9e3SSebastian Grimberg         break;
51689edb9e3SSebastian Grimberg       case CEED_RESTRICTION_ORIENTED:
51777d1c127SSebastian Grimberg         scale = 2;
51889edb9e3SSebastian Grimberg         break;
51989edb9e3SSebastian Grimberg       case CEED_RESTRICTION_CURL_ORIENTED:
52077d1c127SSebastian Grimberg         scale = 6;
52189edb9e3SSebastian Grimberg         break;
5226e15d496SJeremy L Thompson     }
52377d1c127SSebastian Grimberg   } else {
52489edb9e3SSebastian Grimberg     switch (rstr_type) {
52589edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STRIDED:
52689edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STANDARD:
5273ac8f562SJeremy L Thompson       case CEED_RESTRICTION_POINTS:
52877d1c127SSebastian Grimberg         scale = 0;
52989edb9e3SSebastian Grimberg         break;
53089edb9e3SSebastian Grimberg       case CEED_RESTRICTION_ORIENTED:
53177d1c127SSebastian Grimberg         scale = 1;
53289edb9e3SSebastian Grimberg         break;
53389edb9e3SSebastian Grimberg       case CEED_RESTRICTION_CURL_ORIENTED:
53477d1c127SSebastian Grimberg         scale = 5;
53589edb9e3SSebastian Grimberg         break;
53677d1c127SSebastian Grimberg     }
53777d1c127SSebastian Grimberg   }
5386e15d496SJeremy L Thompson   *flops = e_size * scale;
5396e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5406e15d496SJeremy L Thompson }
5416e15d496SJeremy L Thompson 
5427a982d89SJeremy L. Thompson /// @}
5437a982d89SJeremy L. Thompson 
54415910d16Sjeremylt /// @cond DOXYGEN_SKIP
54515910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
54615910d16Sjeremylt /// @endcond
54715910d16Sjeremylt 
5487a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5497a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
5507a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5517a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
552d7b241e6Sjeremylt /// @{
553d7b241e6Sjeremylt 
5547a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
55545f1e315Sjeremylt const CeedInt CEED_STRIDES_BACKEND[3] = {0};
5567a982d89SJeremy L. Thompson 
557ca94c3ddSJeremy L Thompson /// Argument for @ref CeedOperatorSetField() indicating that the field does not require a `CeedElemRestriction`
5582b730f8bSJeremy L Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = &ceed_elemrestriction_none;
5597a982d89SJeremy L. Thompson 
560d7b241e6Sjeremylt /**
561ca94c3ddSJeremy L Thompson   @brief Create a `CeedElemRestriction`
562d7b241e6Sjeremylt 
563ca94c3ddSJeremy L Thompson   @param[in]  ceed        `Ceed` context used to create the `CeedElemRestriction`
564ca94c3ddSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the `offsets` array
565ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
566ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
567fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
568ca94c3ddSJeremy 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`.
569fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
570fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
571ca94c3ddSJeremy L Thompson   @param[in]  mem_type    Memory type of the `offsets` array, see @ref CeedMemType
572ca94c3ddSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the `offsets` array, see @ref CeedCopyMode
573ca94c3ddSJeremy L Thompson   @param[in]  offsets     Array of shape `[num_elem, elem_size]`.
574ca94c3ddSJeremy 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.
575ca94c3ddSJeremy L Thompson                             All offsets must be in the range `[0, l_size - 1]`.
576ca94c3ddSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created `CeedElemRestriction` will be stored
577d7b241e6Sjeremylt 
578b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
579dfdf5a53Sjeremylt 
5807a982d89SJeremy L. Thompson   @ref User
581b11c1e72Sjeremylt **/
5822b730f8bSJeremy L Thompson int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
5832b730f8bSJeremy L Thompson                               CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
5845fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
5855fe0d4faSjeremylt     Ceed delegate;
5866574a04fSJeremy L Thompson 
5872b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
588ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreate");
5892b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
590e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
5915fe0d4faSjeremylt   }
5925fe0d4faSjeremylt 
593e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
5946574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
595ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
596ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
597e022e1f8SJeremy L Thompson 
5982b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
599db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
600d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
601d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
602d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
603d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
604d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
605d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
606*1203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp;
607e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
608e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
60961a27d74SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_STANDARD;
610fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, NULL, *rstr));
611e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
612d7b241e6Sjeremylt }
613d7b241e6Sjeremylt 
614d7b241e6Sjeremylt /**
615ca94c3ddSJeremy L Thompson   @brief Create a `CeedElemRestriction` with orientation signs
616fc0567d9Srezgarshakeri 
617ca94c3ddSJeremy L Thompson   @param[in]  ceed        `Ceed` context used to create the `CeedElemRestriction`
618ca94c3ddSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the `offsets` array
619ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
620ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
621fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
622ca94c3ddSJeremy 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`.
623fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
624fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
625ca94c3ddSJeremy L Thompson   @param[in]  mem_type    Memory type of the `offsets` array, see @ref CeedMemType
626ca94c3ddSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the `offsets` array, see @ref CeedCopyMode
627ca94c3ddSJeremy L Thompson   @param[in]  offsets     Array of shape `[num_elem, elem_size]`.
628ca94c3ddSJeremy 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`.
629ca94c3ddSJeremy L Thompson                             All offsets must be in the range `[0, l_size - 1]`.
630ca94c3ddSJeremy L Thompson   @param[in]  orients     Boolean array of shape `[num_elem, elem_size]` with `false` for positively oriented and `true` to flip the orientation
631ca94c3ddSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created `CeedElemRestriction` will be stored
632fc0567d9Srezgarshakeri 
633fc0567d9Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
634fc0567d9Srezgarshakeri 
635fc0567d9Srezgarshakeri   @ref User
636fc0567d9Srezgarshakeri **/
6372b730f8bSJeremy L Thompson int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
63877d1c127SSebastian Grimberg                                       CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orients,
639fc0567d9Srezgarshakeri                                       CeedElemRestriction *rstr) {
640fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreate) {
641fc0567d9Srezgarshakeri     Ceed delegate;
6426574a04fSJeremy L Thompson 
6432b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
644ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateOriented");
6452b730f8bSJeremy L Thompson     CeedCall(
64677d1c127SSebastian Grimberg         CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, orients, rstr));
647fc0567d9Srezgarshakeri     return CEED_ERROR_SUCCESS;
648fc0567d9Srezgarshakeri   }
649fc0567d9Srezgarshakeri 
650e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
6516574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
652ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
653ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
654e022e1f8SJeremy L Thompson 
6552b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
656db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
657fc0567d9Srezgarshakeri   (*rstr)->ref_count   = 1;
658fc0567d9Srezgarshakeri   (*rstr)->num_elem    = num_elem;
659fc0567d9Srezgarshakeri   (*rstr)->elem_size   = elem_size;
660fc0567d9Srezgarshakeri   (*rstr)->num_comp    = num_comp;
661fc0567d9Srezgarshakeri   (*rstr)->comp_stride = comp_stride;
662fc0567d9Srezgarshakeri   (*rstr)->l_size      = l_size;
663*1203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp;
664e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
665e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
666fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_ORIENTED;
667fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, orients, NULL, *rstr));
66877d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
66977d1c127SSebastian Grimberg }
67077d1c127SSebastian Grimberg 
67177d1c127SSebastian Grimberg /**
672ca94c3ddSJeremy L Thompson   @brief Create a `CeedElemRestriction` with a general tridiagonal transformation matrix for curl-conforming elements
67377d1c127SSebastian Grimberg 
674ca94c3ddSJeremy L Thompson   @param[in]  ceed         `Ceed` context used to create the `CeedElemRestriction`
675ca94c3ddSJeremy L Thompson   @param[in]  num_elem     Number of elements described in the `offsets` array
67677d1c127SSebastian Grimberg   @param[in]  elem_size    Size (number of "nodes") per element
67777d1c127SSebastian Grimberg   @param[in]  num_comp     Number of field components per interpolation node (1 for scalar fields)
678fcbe8c06SSebastian Grimberg   @param[in]  comp_stride  Stride between components for the same L-vector "node".
679ca94c3ddSJeremy 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`.
680fcbe8c06SSebastian Grimberg   @param[in]  l_size       The size of the L-vector.
681fcbe8c06SSebastian Grimberg                              This vector may be larger than the elements and fields given by this restriction.
682ca94c3ddSJeremy L Thompson   @param[in]  mem_type     Memory type of the `offsets` array, see @ref CeedMemType
683ca94c3ddSJeremy L Thompson   @param[in]  copy_mode    Copy mode for the `offsets` array, see @ref CeedCopyMode
684ca94c3ddSJeremy L Thompson   @param[in]  offsets      Array of shape `[num_elem, elem_size]`.
685ca94c3ddSJeremy 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`.
686ca94c3ddSJeremy L Thompson                              All offsets must be in the range `[0, l_size - 1]`.
687ca94c3ddSJeremy 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.
688ca94c3ddSJeremy 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).
689ca94c3ddSJeremy L Thompson   @param[out] rstr         Address of the variable where the newly created `CeedElemRestriction` will be stored
69077d1c127SSebastian Grimberg 
69177d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
69277d1c127SSebastian Grimberg 
69377d1c127SSebastian Grimberg   @ref User
69477d1c127SSebastian Grimberg **/
69577d1c127SSebastian Grimberg int CeedElemRestrictionCreateCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
6960c73c039SSebastian Grimberg                                           CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const CeedInt8 *curl_orients,
69777d1c127SSebastian Grimberg                                           CeedElemRestriction *rstr) {
698fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreate) {
69977d1c127SSebastian Grimberg     Ceed delegate;
70077d1c127SSebastian Grimberg 
70177d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
702ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateCurlOriented");
70377d1c127SSebastian Grimberg     CeedCall(CeedElemRestrictionCreateCurlOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
70477d1c127SSebastian Grimberg                                                    curl_orients, rstr));
70577d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
70677d1c127SSebastian Grimberg   }
70777d1c127SSebastian Grimberg 
708e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
70977d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
710ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
711ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
71277d1c127SSebastian Grimberg 
71377d1c127SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
714fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
71577d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
71677d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
71777d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
71877d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
71977d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
72077d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
721*1203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp;
722e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
723e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
724fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_CURL_ORIENTED;
725fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, curl_orients, *rstr));
726fc0567d9Srezgarshakeri   return CEED_ERROR_SUCCESS;
727fc0567d9Srezgarshakeri }
728fc0567d9Srezgarshakeri 
729fc0567d9Srezgarshakeri /**
730ca94c3ddSJeremy L Thompson   @brief Create a strided `CeedElemRestriction`
731d7b241e6Sjeremylt 
732ca94c3ddSJeremy L Thompson   @param[in]  ceed      `Ceed` context used to create the `CeedElemRestriction`
733ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
734ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
735ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation "node" (1 for scalar fields)
736fcbe8c06SSebastian Grimberg   @param[in]  l_size    The size of the L-vector.
737fcbe8c06SSebastian Grimberg                           This vector may be larger than the elements and fields given by this restriction.
738ca94c3ddSJeremy L Thompson   @param[in]  strides   Array for strides between `[nodes, components, elements]`.
739ca94c3ddSJeremy 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]`.
740ca94c3ddSJeremy L Thompson                           @ref CEED_STRIDES_BACKEND may be used for `CeedVector` ordered by the same `Ceed` backend.
741972f909dSJeremy L Thompson                           `CEED_STRIDES_BACKEND` should only be used pass data between `CeedOperator` created with the same `Ceed` backend.
742972f909dSJeremy L Thompson                           The L-vector layout will, in general, be different between `Ceed` backends.
743ca94c3ddSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created `CeedElemRestriction` will be stored
744d7b241e6Sjeremylt 
745b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
746dfdf5a53Sjeremylt 
7477a982d89SJeremy L. Thompson   @ref User
748b11c1e72Sjeremylt **/
7492b730f8bSJeremy L Thompson int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedSize l_size, const CeedInt strides[3],
750f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
7515fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
7525fe0d4faSjeremylt     Ceed delegate;
753b04eb3d9SSebastian Grimberg 
7542b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
755ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateStrided");
7562b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, l_size, strides, rstr));
757e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
7585fe0d4faSjeremylt   }
7595fe0d4faSjeremylt 
760e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
7616574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
762ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
763e7f679fcSJeremy L Thompson   CeedCheck(l_size >= num_elem * elem_size * num_comp, ceed, CEED_ERROR_DIMENSION, "L-vector size must be at least num_elem * elem_size * num_comp");
764e022e1f8SJeremy L Thompson 
7652b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
766db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
767d1d35e2fSjeremylt   (*rstr)->ref_count  = 1;
768d1d35e2fSjeremylt   (*rstr)->num_elem   = num_elem;
769d1d35e2fSjeremylt   (*rstr)->elem_size  = elem_size;
770d1d35e2fSjeremylt   (*rstr)->num_comp   = num_comp;
771d1d35e2fSjeremylt   (*rstr)->l_size     = l_size;
772*1203703bSJeremy L Thompson   (*rstr)->e_size     = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp;
773e7f679fcSJeremy L Thompson   (*rstr)->num_block  = num_elem;
774e7f679fcSJeremy L Thompson   (*rstr)->block_size = 1;
775fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type  = CEED_RESTRICTION_STRIDED;
7762b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
7772b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
778fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
779e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
780d7b241e6Sjeremylt }
781d7b241e6Sjeremylt 
782d7b241e6Sjeremylt /**
783ca94c3ddSJeremy 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.
7843ac8f562SJeremy L Thompson 
7853ac8f562SJeremy L Thompson   The offsets array is arranged as
7863ac8f562SJeremy L Thompson 
7873ac8f562SJeremy L Thompson   element_0_start_index
7883ac8f562SJeremy L Thompson   element_1_start_index
7893ac8f562SJeremy L Thompson   ...
7903ac8f562SJeremy L Thompson   element_n_start_index
7913ac8f562SJeremy L Thompson   element_n_stop_index
7923ac8f562SJeremy L Thompson   element_0_point_0
7933ac8f562SJeremy L Thompson   element_0_point_1
7943ac8f562SJeremy L Thompson   ...
7953ac8f562SJeremy L Thompson 
796ca94c3ddSJeremy L Thompson   @param[in]  ceed       `Ceed` context used to create the `CeedElemRestriction`
797ca94c3ddSJeremy L Thompson   @param[in]  num_elem   Number of elements described in the `offsets` array
798ca94c3ddSJeremy L Thompson   @param[in]  num_points Number of points described in the `offsets` array
7993ac8f562SJeremy L Thompson   @param[in]  num_comp   Number of field components per interpolation node (1 for scalar fields).
8003ac8f562SJeremy L Thompson                            Components are assumed to be contiguous by point.
8013ac8f562SJeremy L Thompson   @param[in]  l_size     The size of the L-vector.
8023ac8f562SJeremy L Thompson                            This vector may be larger than the elements and fields given by this restriction.
803ca94c3ddSJeremy L Thompson   @param[in]  mem_type   Memory type of the `offsets` array, see @ref CeedMemType
804ca94c3ddSJeremy L Thompson   @param[in]  copy_mode  Copy mode for the `offsets` array, see @ref CeedCopyMode
805ca94c3ddSJeremy L Thompson   @param[in]  offsets    Array of size `num_elem + 1 + num_points`.
8063ac8f562SJeremy L Thompson                            The first portion of the offsets array holds the ranges of indices corresponding to each element.
8073ac8f562SJeremy L Thompson                            The second portion holds the indices for each element.
808ca94c3ddSJeremy L Thompson   @param[out] rstr       Address of the variable where the newly created `CeedElemRestriction` will be stored
8093ac8f562SJeremy L Thompson 
8103ac8f562SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
8113ac8f562SJeremy L Thompson 
8123ac8f562SJeremy L Thompson   @ref Backend
8133ac8f562SJeremy L Thompson  **/
8143ac8f562SJeremy L Thompson int CeedElemRestrictionCreateAtPoints(Ceed ceed, CeedInt num_elem, CeedInt num_points, CeedInt num_comp, CeedSize l_size, CeedMemType mem_type,
8153ac8f562SJeremy L Thompson                                       CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
8163ac8f562SJeremy L Thompson   if (!ceed->ElemRestrictionCreateAtPoints) {
8173ac8f562SJeremy L Thompson     Ceed delegate;
8183ac8f562SJeremy L Thompson 
8193ac8f562SJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
820ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateAtPoints");
8213ac8f562SJeremy L Thompson     CeedCall(CeedElemRestrictionCreateAtPoints(delegate, num_elem, num_points, num_comp, l_size, mem_type, copy_mode, offsets, rstr));
8223ac8f562SJeremy L Thompson     return CEED_ERROR_SUCCESS;
8233ac8f562SJeremy L Thompson   }
8243ac8f562SJeremy L Thompson 
8253ac8f562SJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
8263ac8f562SJeremy L Thompson   CeedCheck(num_points >= 0, ceed, CEED_ERROR_DIMENSION, "Number of points must be non-negative");
827ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
8283ac8f562SJeremy L Thompson   CeedCheck(l_size >= num_points * num_comp, ceed, CEED_ERROR_DIMENSION, "L-vector must be at least num_points * num_comp");
8293ac8f562SJeremy L Thompson 
8303ac8f562SJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
8313ac8f562SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
8323ac8f562SJeremy L Thompson   (*rstr)->ref_count  = 1;
8333ac8f562SJeremy L Thompson   (*rstr)->num_elem   = num_elem;
8343ac8f562SJeremy L Thompson   (*rstr)->num_points = num_points;
8353ac8f562SJeremy L Thompson   (*rstr)->num_comp   = num_comp;
8363ac8f562SJeremy L Thompson   (*rstr)->l_size     = l_size;
837*1203703bSJeremy L Thompson   (*rstr)->e_size     = (CeedSize)num_points * (CeedSize)num_comp;
83805fa913cSJeremy L Thompson   (*rstr)->num_block  = num_elem;
8393ac8f562SJeremy L Thompson   (*rstr)->block_size = 1;
8403ac8f562SJeremy L Thompson   (*rstr)->rstr_type  = CEED_RESTRICTION_POINTS;
8413ac8f562SJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateAtPoints(mem_type, copy_mode, offsets, NULL, NULL, *rstr));
8423ac8f562SJeremy L Thompson   return CEED_ERROR_SUCCESS;
8433ac8f562SJeremy L Thompson }
8443ac8f562SJeremy L Thompson 
8453ac8f562SJeremy L Thompson /**
846ca94c3ddSJeremy L Thompson   @brief Create a blocked `CeedElemRestriction`, typically only used by backends
847d7b241e6Sjeremylt 
848ca94c3ddSJeremy L Thompson   @param[in]  ceed        `Ceed` context used to create the `CeedElemRestriction`
849ca94c3ddSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the `offsets` array
850ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of unknowns) per element
851e7f679fcSJeremy L Thompson   @param[in]  block_size  Number of elements in a block
852ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
853fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
854ca94c3ddSJeremy 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`.
855fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
856fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
857ca94c3ddSJeremy L Thompson   @param[in]  mem_type    Memory type of the `offsets` array, see @ref CeedMemType
858ca94c3ddSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the `offsets` array, see @ref CeedCopyMode
859ca94c3ddSJeremy L Thompson   @param[in]  offsets     Array of shape `[num_elem, elem_size]`.
860ca94c3ddSJeremy 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`.
861ca94c3ddSJeremy L Thompson                             All offsets must be in the range `[0, l_size - 1]`.
862ca94c3ddSJeremy L Thompson                             The backend will permute and pad this array to the desired ordering for the blocksize, which is typically given by the backend.
863ca94c3ddSJeremy L Thompson                             The default reordering is to interlace elements.
864ca94c3ddSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created `CeedElemRestriction` will be stored
865d7b241e6Sjeremylt 
866b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
867dfdf5a53Sjeremylt 
8687a982d89SJeremy L. Thompson   @ref Backend
869b11c1e72Sjeremylt  **/
870e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedInt comp_stride,
8712b730f8bSJeremy L Thompson                                      CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets,
8724ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
8731c66c397SJeremy L Thompson   CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
874d7b241e6Sjeremylt 
8755fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
8765fe0d4faSjeremylt     Ceed delegate;
8776574a04fSJeremy L Thompson 
8782b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
879ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlocked");
880e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
881e7f679fcSJeremy L Thompson                                               rstr));
882e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
8835fe0d4faSjeremylt   }
884d7b241e6Sjeremylt 
885e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
8866574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
887e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
888ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
889ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
890e022e1f8SJeremy L Thompson 
891e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
892e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
893d7b241e6Sjeremylt 
894db002c03SJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
895db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
896d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
897d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
898d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
899d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
900d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
901d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
902*1203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
903e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
904e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
90561a27d74SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_STANDARD;
906e7f679fcSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL, NULL, *rstr));
9071c66c397SJeremy L Thompson   if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
908e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
909d7b241e6Sjeremylt }
910d7b241e6Sjeremylt 
911b11c1e72Sjeremylt /**
912ca94c3ddSJeremy L Thompson   @brief Create a blocked oriented `CeedElemRestriction`, typically only used by backends
91377d1c127SSebastian Grimberg 
914ca94c3ddSJeremy L Thompson   @param[in]  ceed        `Ceed` context used to create the `CeedElemRestriction`
915ca94c3ddSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the `offsets` array.
91677d1c127SSebastian Grimberg   @param[in]  elem_size   Size (number of unknowns) per element
917e7f679fcSJeremy L Thompson   @param[in]  block_size  Number of elements in a block
91877d1c127SSebastian Grimberg   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
919fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
920ca94c3ddSJeremy 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`.
921fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
922fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
923ca94c3ddSJeremy L Thompson   @param[in]  mem_type    Memory type of the `offsets` array, see @ref CeedMemType
924ca94c3ddSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the `offsets` array, see @ref CeedCopyMode
925ca94c3ddSJeremy L Thompson   @param[in]  offsets     Array of shape `[num_elem, elem_size]`.
926ca94c3ddSJeremy 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`.
927ca94c3ddSJeremy L Thompson                             All offsets must be in the range `[0, l_size - 1]`.
928ca94c3ddSJeremy L Thompson                             The backend will permute and pad this array to the desired ordering for the blocksize, which is typically given by the backend.
929ca94c3ddSJeremy L Thompson                             The default reordering is to interlace elements.
930ca94c3ddSJeremy L Thompson   @param[in]  orients     Boolean array of shape `[num_elem, elem_size]` with `false` for positively oriented and `true` to flip the orientation.
931ca94c3ddSJeremy L Thompson                             Will also be permuted and padded similarly to `offsets`.
932ca94c3ddSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created `CeedElemRestriction` will be stored
93377d1c127SSebastian Grimberg 
93477d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
93577d1c127SSebastian Grimberg 
93677d1c127SSebastian Grimberg   @ref Backend
93777d1c127SSebastian Grimberg  **/
938e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp,
939e7f679fcSJeremy L Thompson                                              CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode,
940e7f679fcSJeremy L Thompson                                              const CeedInt *offsets, const bool *orients, CeedElemRestriction *rstr) {
941e7f679fcSJeremy L Thompson   bool    *block_orients;
9421c66c397SJeremy L Thompson   CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
94377d1c127SSebastian Grimberg 
944fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreateBlocked) {
94577d1c127SSebastian Grimberg     Ceed delegate;
94677d1c127SSebastian Grimberg 
94777d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
948ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedOriented");
949e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode,
95077d1c127SSebastian Grimberg                                                       offsets, orients, rstr));
95177d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
95277d1c127SSebastian Grimberg   }
95377d1c127SSebastian Grimberg 
95477d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
955e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
956ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
957ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
95877d1c127SSebastian Grimberg 
959e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
960e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_orients));
961e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
962e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOrients(orients, block_orients, num_block, num_elem, block_size, elem_size));
96377d1c127SSebastian Grimberg 
964fcbe8c06SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
965fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
96677d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
96777d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
96877d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
96977d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
97077d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
97177d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
972*1203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
973e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
974e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
975fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_ORIENTED;
976e7f679fcSJeremy L Thompson   CeedCall(
977e7f679fcSJeremy L Thompson       ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, (const bool *)block_orients, NULL, *rstr));
9781c66c397SJeremy L Thompson   if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
97977d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
98077d1c127SSebastian Grimberg }
98177d1c127SSebastian Grimberg 
98277d1c127SSebastian Grimberg /**
983ca94c3ddSJeremy L Thompson   @brief Create a blocked curl-oriented `CeedElemRestriction`, typically only used by backends
98477d1c127SSebastian Grimberg 
985ca94c3ddSJeremy L Thompson   @param[in]  ceed         `Ceed` context used to create the `CeedElemRestriction`
986ca94c3ddSJeremy L Thompson   @param[in]  num_elem     Number of elements described in the `offsets` array.
98777d1c127SSebastian Grimberg   @param[in]  elem_size    Size (number of unknowns) per element
988e7f679fcSJeremy L Thompson   @param[in]  block_size   Number of elements in a block
98977d1c127SSebastian Grimberg   @param[in]  num_comp     Number of field components per interpolation node (1 for scalar fields)
990fcbe8c06SSebastian Grimberg   @param[in]  comp_stride  Stride between components for the same L-vector "node".
991ca94c3ddSJeremy 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`.
992fcbe8c06SSebastian Grimberg   @param[in]  l_size       The size of the L-vector.
993fcbe8c06SSebastian Grimberg                              This vector may be larger than the elements and fields given by this restriction.
994ca94c3ddSJeremy L Thompson   @param[in]  mem_type     Memory type of the `offsets` array, see @ref CeedMemType
995ca94c3ddSJeremy L Thompson   @param[in]  copy_mode    Copy mode for the `offsets` array, see @ref CeedCopyMode
996ca94c3ddSJeremy L Thompson   @param[in]  offsets      Array of shape `[num_elem, elem_size]`.
997ca94c3ddSJeremy 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`.
998ca94c3ddSJeremy L Thompson                              All offsets must be in the range `[0, l_size - 1]`.
999ca94c3ddSJeremy L Thompson                              The backend will permute and pad this array to the desired  ordering for the blocksize, which is typically given by the backend.
1000ca94c3ddSJeremy L Thompson                              The default reordering is to interlace elements.
1001ca94c3ddSJeremy 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.
1002ca94c3ddSJeremy 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).
1003ca94c3ddSJeremy L Thompson                              Will also be permuted and padded similarly to offsets.
1004ca94c3ddSJeremy L Thompson   @param[out] rstr         Address of the variable where the newly created `CeedElemRestriction` will be stored
100577d1c127SSebastian Grimberg 
100677d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
100777d1c127SSebastian Grimberg 
100877d1c127SSebastian Grimberg   @ref Backend
100977d1c127SSebastian Grimberg  **/
1010e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp,
101177d1c127SSebastian Grimberg                                                  CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode,
10120c73c039SSebastian Grimberg                                                  const CeedInt *offsets, const CeedInt8 *curl_orients, CeedElemRestriction *rstr) {
1013e7f679fcSJeremy L Thompson   CeedInt8 *block_curl_orients;
10141c66c397SJeremy L Thompson   CeedInt  *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
101577d1c127SSebastian Grimberg 
1016fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreateBlocked) {
101777d1c127SSebastian Grimberg     Ceed delegate;
101877d1c127SSebastian Grimberg 
101977d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
1020ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedCurlOriented");
1021e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedCurlOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type,
1022e7f679fcSJeremy L Thompson                                                           copy_mode, offsets, curl_orients, rstr));
102377d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
102477d1c127SSebastian Grimberg   }
102577d1c127SSebastian Grimberg 
1026e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
102777d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
1028e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
1029ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
1030ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
103177d1c127SSebastian Grimberg 
1032e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
1033e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * 3 * elem_size, &block_curl_orients));
1034e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
1035e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadCurlOrients(curl_orients, block_curl_orients, num_block, num_elem, block_size, 3 * elem_size));
103677d1c127SSebastian Grimberg 
1037fcbe8c06SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
1038fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
103977d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
104077d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
104177d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
104277d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
104377d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
104477d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
1045*1203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1046e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
1047e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
1048fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_CURL_ORIENTED;
1049e7f679fcSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL,
1050e7f679fcSJeremy L Thompson                                               (const CeedInt8 *)block_curl_orients, *rstr));
10511c66c397SJeremy L Thompson   if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
105277d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
105377d1c127SSebastian Grimberg }
105477d1c127SSebastian Grimberg 
105577d1c127SSebastian Grimberg /**
1056ca94c3ddSJeremy L Thompson   @brief Create a blocked strided `CeedElemRestriction`, typically only used by backends
10577509a596Sjeremylt 
1058ca94c3ddSJeremy L Thompson   @param[in]  ceed        `Ceed` context used to create the `CeedElemRestriction`
1059ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described by the restriction
1060ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
1061e7f679fcSJeremy L Thompson   @param[in]  block_size  Number of elements in a block
1062ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
1063fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
1064fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
1065ca94c3ddSJeremy L Thompson   @param[in]  strides     Array for strides between `[nodes, components, elements]`.
1066ca94c3ddSJeremy 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]`.
1067ca94c3ddSJeremy L Thompson                             @ref CEED_STRIDES_BACKEND may be used for `CeedVector` ordered by the same `Ceed` backend.
1068ca94c3ddSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created `CeedElemRestriction` will be stored
10697509a596Sjeremylt 
10707509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
10717509a596Sjeremylt 
10727a982d89SJeremy L. Thompson   @ref User
10737509a596Sjeremylt **/
1074e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedSize l_size,
10758621c6c6SJeremy L Thompson                                             const CeedInt strides[3], CeedElemRestriction *rstr) {
1076e7f679fcSJeremy L Thompson   CeedInt num_block = (num_elem / block_size) + !!(num_elem % block_size);
10777509a596Sjeremylt 
10787509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
10797509a596Sjeremylt     Ceed delegate;
10806574a04fSJeremy L Thompson 
10812b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
1082ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedStrided");
1083e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, block_size, num_comp, l_size, strides, rstr));
1084e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
10857509a596Sjeremylt   }
10867509a596Sjeremylt 
1087e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
10886574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
1089e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
1090ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
1091e7f679fcSJeremy L Thompson   CeedCheck(l_size >= num_elem * elem_size * num_comp, ceed, CEED_ERROR_DIMENSION, "L-vector size must be at least num_elem * elem_size * num_comp");
1092e022e1f8SJeremy L Thompson 
10932b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
1094db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
1095d1d35e2fSjeremylt   (*rstr)->ref_count  = 1;
1096d1d35e2fSjeremylt   (*rstr)->num_elem   = num_elem;
1097d1d35e2fSjeremylt   (*rstr)->elem_size  = elem_size;
1098d1d35e2fSjeremylt   (*rstr)->num_comp   = num_comp;
1099d1d35e2fSjeremylt   (*rstr)->l_size     = l_size;
1100*1203703bSJeremy L Thompson   (*rstr)->e_size     = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1101e7f679fcSJeremy L Thompson   (*rstr)->num_block  = num_block;
1102e7f679fcSJeremy L Thompson   (*rstr)->block_size = block_size;
1103fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type  = CEED_RESTRICTION_STRIDED;
11042b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
11052b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
1106fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
1107e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
11087509a596Sjeremylt }
11097509a596Sjeremylt 
11107509a596Sjeremylt /**
1111ca94c3ddSJeremy L Thompson   @brief Copy the pointer to a `CeedElemRestriction` and set @ref CeedElemRestrictionApply() implementation to use the unsigned version.
1112c17ec2beSJeremy L Thompson 
1113ca94c3ddSJeremy L Thompson   Both pointers should be destroyed with @ref CeedElemRestrictionDestroy().
1114c17ec2beSJeremy L Thompson 
1115ca94c3ddSJeremy L Thompson   @param[in]     rstr          `CeedElemRestriction` to create unsigned reference to
1116ca94c3ddSJeremy L Thompson   @param[in,out] rstr_unsigned Variable to store unsigned `CeedElemRestriction`
1117c17ec2beSJeremy L Thompson 
1118c17ec2beSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1119c17ec2beSJeremy L Thompson 
1120c17ec2beSJeremy L Thompson   @ref User
1121c17ec2beSJeremy L Thompson **/
1122c17ec2beSJeremy L Thompson int CeedElemRestrictionCreateUnsignedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unsigned) {
1123c17ec2beSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr_unsigned));
1124c17ec2beSJeremy L Thompson 
1125c17ec2beSJeremy L Thompson   // Copy old rstr
1126c17ec2beSJeremy L Thompson   memcpy(*rstr_unsigned, rstr, sizeof(struct CeedElemRestriction_private));
1127c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ceed = NULL;
1128c17ec2beSJeremy L Thompson   CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unsigned)->ceed));
1129c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ref_count = 1;
1130c17ec2beSJeremy L Thompson   (*rstr_unsigned)->strides   = NULL;
1131c17ec2beSJeremy L Thompson   if (rstr->strides) {
1132c17ec2beSJeremy L Thompson     CeedCall(CeedMalloc(3, &(*rstr_unsigned)->strides));
1133c17ec2beSJeremy L Thompson     for (CeedInt i = 0; i < 3; i++) (*rstr_unsigned)->strides[i] = rstr->strides[i];
1134c17ec2beSJeremy L Thompson   }
11357c1dbaffSSebastian Grimberg   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unsigned)->rstr_base));
1136c17ec2beSJeremy L Thompson 
1137c17ec2beSJeremy L Thompson   // Override Apply
1138c17ec2beSJeremy L Thompson   (*rstr_unsigned)->Apply = rstr->ApplyUnsigned;
1139c17ec2beSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1140c17ec2beSJeremy L Thompson }
1141c17ec2beSJeremy L Thompson 
1142c17ec2beSJeremy L Thompson /**
1143ca94c3ddSJeremy L Thompson   @brief Copy the pointer to a `CeedElemRestriction` and set @ref CeedElemRestrictionApply() implementation to use the unoriented version.
11447c1dbaffSSebastian Grimberg 
1145ca94c3ddSJeremy L Thompson   Both pointers should be destroyed with @ref CeedElemRestrictionDestroy().
11467c1dbaffSSebastian Grimberg 
1147ca94c3ddSJeremy L Thompson   @param[in]     rstr            `CeedElemRestriction` to create unoriented reference to
1148ca94c3ddSJeremy L Thompson   @param[in,out] rstr_unoriented Variable to store unoriented `CeedElemRestriction`
11497c1dbaffSSebastian Grimberg 
11507c1dbaffSSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
11517c1dbaffSSebastian Grimberg 
11527c1dbaffSSebastian Grimberg   @ref User
11537c1dbaffSSebastian Grimberg **/
11547c1dbaffSSebastian Grimberg int CeedElemRestrictionCreateUnorientedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unoriented) {
11557c1dbaffSSebastian Grimberg   CeedCall(CeedCalloc(1, rstr_unoriented));
11567c1dbaffSSebastian Grimberg 
11577c1dbaffSSebastian Grimberg   // Copy old rstr
11587c1dbaffSSebastian Grimberg   memcpy(*rstr_unoriented, rstr, sizeof(struct CeedElemRestriction_private));
11597c1dbaffSSebastian Grimberg   (*rstr_unoriented)->ceed = NULL;
11607c1dbaffSSebastian Grimberg   CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unoriented)->ceed));
11617c1dbaffSSebastian Grimberg   (*rstr_unoriented)->ref_count = 1;
11627c1dbaffSSebastian Grimberg   (*rstr_unoriented)->strides   = NULL;
11637c1dbaffSSebastian Grimberg   if (rstr->strides) {
11647c1dbaffSSebastian Grimberg     CeedCall(CeedMalloc(3, &(*rstr_unoriented)->strides));
11657c1dbaffSSebastian Grimberg     for (CeedInt i = 0; i < 3; i++) (*rstr_unoriented)->strides[i] = rstr->strides[i];
11667c1dbaffSSebastian Grimberg   }
11677c1dbaffSSebastian Grimberg   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unoriented)->rstr_base));
11687c1dbaffSSebastian Grimberg 
11697c1dbaffSSebastian Grimberg   // Override Apply
11707c1dbaffSSebastian Grimberg   (*rstr_unoriented)->Apply = rstr->ApplyUnoriented;
11717c1dbaffSSebastian Grimberg   return CEED_ERROR_SUCCESS;
11727c1dbaffSSebastian Grimberg }
11737c1dbaffSSebastian Grimberg 
11747c1dbaffSSebastian Grimberg /**
1175ca94c3ddSJeremy L Thompson   @brief Copy the pointer to a `CeedElemRestriction`.
11769fd66db6SSebastian Grimberg 
1177ca94c3ddSJeremy L Thompson   Both pointers should be destroyed with @ref CeedElemRestrictionDestroy().
11789560d06aSjeremylt 
1179ca94c3ddSJeremy 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`.
1180ca94c3ddSJeremy L Thompson         This `CeedElemRestriction` will be destroyed if `*rstr_copy` is the only reference to this `CeedElemRestriction`.
1181ea61e9acSJeremy L Thompson 
1182ca94c3ddSJeremy L Thompson   @param[in]     rstr      `CeedElemRestriction` to copy reference to
1183ea61e9acSJeremy L Thompson   @param[in,out] rstr_copy Variable to store copied reference
11849560d06aSjeremylt 
11859560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
11869560d06aSjeremylt 
11879560d06aSjeremylt   @ref User
11889560d06aSjeremylt **/
11892b730f8bSJeremy L Thompson int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_copy) {
1190393ac2cdSJeremy L Thompson   if (rstr != CEED_ELEMRESTRICTION_NONE) CeedCall(CeedElemRestrictionReference(rstr));
11912b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionDestroy(rstr_copy));
11929560d06aSjeremylt   *rstr_copy = rstr;
11939560d06aSjeremylt   return CEED_ERROR_SUCCESS;
11949560d06aSjeremylt }
11959560d06aSjeremylt 
11969560d06aSjeremylt /**
1197ca94c3ddSJeremy L Thompson   @brief Create `CeedVector` associated with a `CeedElemRestriction`
1198b11c1e72Sjeremylt 
1199ca94c3ddSJeremy L Thompson   @param[in]  rstr  `CeedElemRestriction`
1200ca94c3ddSJeremy L Thompson   @param[out] l_vec The address of the L-vector to be created, or `NULL`
1201ca94c3ddSJeremy L Thompson   @param[out] e_vec The address of the E-vector to be created, or `NULL`
1202b11c1e72Sjeremylt 
1203b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1204dfdf5a53Sjeremylt 
12057a982d89SJeremy L. Thompson   @ref User
1206b11c1e72Sjeremylt **/
12072b730f8bSJeremy L Thompson int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, CeedVector *e_vec) {
1208d2643443SJeremy L Thompson   CeedSize e_size, l_size;
1209*1203703bSJeremy L Thompson   Ceed     ceed;
121048acf710SJeremy L Thompson 
1211*1203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
1212*1203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &l_size));
1213*1203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &e_size));
1214*1203703bSJeremy L Thompson   if (l_vec) CeedCall(CeedVectorCreate(ceed, l_size, l_vec));
1215*1203703bSJeremy L Thompson   if (e_vec) CeedCall(CeedVectorCreate(ceed, e_size, e_vec));
1216e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1217d7b241e6Sjeremylt }
1218d7b241e6Sjeremylt 
1219d7b241e6Sjeremylt /**
1220d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
1221d7b241e6Sjeremylt 
1222ca94c3ddSJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
1223ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1224ca94c3ddSJeremy L Thompson   @param[in]  u       Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE)
1225ca94c3ddSJeremy L Thompson   @param[out] ru      Output vector (of shape `[num_elem * elem_size]` when `t_mode` = @ref CEED_NOTRANSPOSE).
1226fcbe8c06SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
1227ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
1228b11c1e72Sjeremylt 
1229b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1230dfdf5a53Sjeremylt 
12317a982d89SJeremy L. Thompson   @ref User
1232b11c1e72Sjeremylt **/
12332b730f8bSJeremy L Thompson int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
1234701e7d35SJeremy L Thompson   CeedSize min_u_len, min_ru_len, len;
1235701e7d35SJeremy L Thompson   CeedInt  num_elem;
1236*1203703bSJeremy L Thompson   Ceed     ceed;
1237d7b241e6Sjeremylt 
1238*1203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
1239d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
1240701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &min_ru_len));
1241701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_u_len));
1242d7b241e6Sjeremylt   } else {
1243701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &min_u_len));
1244701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_ru_len));
1245d7b241e6Sjeremylt   }
1246701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(u, &len));
1247*1203703bSJeremy L Thompson   CeedCheck(min_u_len <= len, ceed, CEED_ERROR_DIMENSION,
1248701e7d35SJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_ru_len,
1249701e7d35SJeremy L Thompson             min_u_len);
1250701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(ru, &len));
1251*1203703bSJeremy L Thompson   CeedCheck(min_ru_len <= len, ceed, CEED_ERROR_DIMENSION,
1252701e7d35SJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_u_len,
1253701e7d35SJeremy L Thompson             min_ru_len);
1254701e7d35SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
1255701e7d35SJeremy L Thompson   if (num_elem > 0) CeedCall(rstr->Apply(rstr, t_mode, u, ru, request));
1256e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1257d7b241e6Sjeremylt }
1258d7b241e6Sjeremylt 
1259d7b241e6Sjeremylt /**
12603ac8f562SJeremy L Thompson   @brief Restrict an L-vector of points to a single element or apply its transpose
12613ac8f562SJeremy L Thompson 
1262ca94c3ddSJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
1263ca94c3ddSJeremy L Thompson   @param[in]  elem    Element number in range `[0, num_elem)`
12643ac8f562SJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1265ca94c3ddSJeremy L Thompson   @param[in]  u       Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE)
1266ca94c3ddSJeremy L Thompson   @param[out] ru      Output vector (of shape [`num_points * num_comp]` when `t_mode` = @ref CEED_NOTRANSPOSE).
12673ac8f562SJeremy L Thompson                         Ordering of the e-vector is decided by the backend.
12683ac8f562SJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
12693ac8f562SJeremy L Thompson 
12703ac8f562SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
12713ac8f562SJeremy L Thompson 
12723ac8f562SJeremy L Thompson   @ref User
12733ac8f562SJeremy L Thompson **/
127405fa913cSJeremy L Thompson int CeedElemRestrictionApplyAtPointsInElement(CeedElemRestriction rstr, CeedInt elem, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
12753ac8f562SJeremy L Thompson                                               CeedRequest *request) {
1276701e7d35SJeremy L Thompson   CeedSize min_u_len, min_ru_len, len;
1277701e7d35SJeremy L Thompson   CeedInt  num_elem;
1278*1203703bSJeremy L Thompson   Ceed     ceed;
12793ac8f562SJeremy L Thompson 
1280*1203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
12813ac8f562SJeremy L Thompson   if (t_mode == CEED_NOTRANSPOSE) {
1282701e7d35SJeremy L Thompson     CeedInt num_points, num_comp;
1283701e7d35SJeremy L Thompson 
1284701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_u_len));
1285701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, elem, &num_points));
1286701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
1287701e7d35SJeremy L Thompson     min_ru_len = (CeedSize)num_points * (CeedSize)num_comp;
12883ac8f562SJeremy L Thompson   } else {
1289701e7d35SJeremy L Thompson     CeedInt num_points, num_comp;
1290701e7d35SJeremy L Thompson 
1291701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, elem, &num_points));
1292701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
1293701e7d35SJeremy L Thompson     min_u_len = (CeedSize)num_points * (CeedSize)num_comp;
1294701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_ru_len));
12953ac8f562SJeremy L Thompson   }
1296701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(u, &len));
1297*1203703bSJeremy L Thompson   CeedCheck(min_u_len <= len, ceed, CEED_ERROR_DIMENSION,
12983ac8f562SJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT
12993ac8f562SJeremy L Thompson             ") for element %" CeedInt_FMT,
1300701e7d35SJeremy L Thompson             len, min_ru_len, min_u_len, elem);
1301701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(ru, &len));
1302*1203703bSJeremy L Thompson   CeedCheck(min_ru_len <= len, ceed, CEED_ERROR_DIMENSION,
13033ac8f562SJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT
13043ac8f562SJeremy L Thompson             ") for element %" CeedInt_FMT,
1305701e7d35SJeremy L Thompson             len, min_ru_len, min_u_len, elem);
1306701e7d35SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
1307*1203703bSJeremy L Thompson   CeedCheck(elem < num_elem, ceed, CEED_ERROR_DIMENSION,
1308701e7d35SJeremy L Thompson             "Cannot retrieve element %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", elem, elem, num_elem);
1309701e7d35SJeremy L Thompson   if (num_elem > 0) CeedCall(rstr->ApplyAtPointsInElement(rstr, elem, t_mode, u, ru, request));
13103ac8f562SJeremy L Thompson   return CEED_ERROR_SUCCESS;
13113ac8f562SJeremy L Thompson }
13123ac8f562SJeremy L Thompson 
13133ac8f562SJeremy L Thompson /**
1314d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
1315be9261b7Sjeremylt 
1316ca94c3ddSJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
1317ca94c3ddSJeremy 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]`
1318ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1319ca94c3ddSJeremy L Thompson   @param[in]  u       Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE)
1320ca94c3ddSJeremy L Thompson   @param[out] ru      Output vector (of shape `[block_size * elem_size]` when `t_mode` = @ref CEED_NOTRANSPOSE).
1321fcbe8c06SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
1322ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
1323be9261b7Sjeremylt 
1324be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
1325be9261b7Sjeremylt 
13267a982d89SJeremy L. Thompson   @ref Backend
1327be9261b7Sjeremylt **/
13282b730f8bSJeremy L Thompson int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
13292b730f8bSJeremy L Thompson                                   CeedRequest *request) {
1330701e7d35SJeremy L Thompson   CeedSize min_u_len, min_ru_len, len;
1331701e7d35SJeremy L Thompson   CeedInt  block_size, num_elem;
1332*1203703bSJeremy L Thompson   Ceed     ceed;
1333be9261b7Sjeremylt 
1334*1203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
1335*1203703bSJeremy L Thompson   CeedCheck(rstr->ApplyBlock, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionApplyBlock");
13366402da51SJeremy L Thompson 
1337701e7d35SJeremy L Thompson   CeedCall(CeedElemRestrictionGetBlockSize(rstr, &block_size));
1338d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
1339701e7d35SJeremy L Thompson     CeedInt elem_size, num_comp;
1340701e7d35SJeremy L Thompson 
1341701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetElementSize(rstr, &elem_size));
1342701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
1343701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_u_len));
1344701e7d35SJeremy L Thompson     min_ru_len = (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1345be9261b7Sjeremylt   } else {
1346701e7d35SJeremy L Thompson     CeedInt elem_size, num_comp;
1347701e7d35SJeremy L Thompson 
1348701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetElementSize(rstr, &elem_size));
1349701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
1350701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_ru_len));
1351701e7d35SJeremy L Thompson     min_u_len = (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1352be9261b7Sjeremylt   }
1353701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(u, &len));
1354*1203703bSJeremy L Thompson   CeedCheck(min_u_len == len, ceed, CEED_ERROR_DIMENSION,
1355701e7d35SJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_u_len,
1356701e7d35SJeremy L Thompson             min_ru_len);
1357701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(ru, &len));
1358*1203703bSJeremy L Thompson   CeedCheck(min_ru_len == len, ceed, CEED_ERROR_DIMENSION,
1359701e7d35SJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_ru_len,
1360701e7d35SJeremy L Thompson             min_u_len);
1361701e7d35SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
1362*1203703bSJeremy L Thompson   CeedCheck(block_size * block <= num_elem, ceed, CEED_ERROR_DIMENSION,
1363701e7d35SJeremy L Thompson             "Cannot retrieve block %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", block, block_size * block,
1364701e7d35SJeremy L Thompson             num_elem);
13652b730f8bSJeremy L Thompson   CeedCall(rstr->ApplyBlock(rstr, block, t_mode, u, ru, request));
1366e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1367be9261b7Sjeremylt }
1368be9261b7Sjeremylt 
1369be9261b7Sjeremylt /**
1370ca94c3ddSJeremy L Thompson   @brief Get the `Ceed` associated with a `CeedElemRestriction`
1371b7c9bbdaSJeremy L Thompson 
1372ca94c3ddSJeremy L Thompson   @param[in]  rstr `CeedElemRestriction`
1373ca94c3ddSJeremy L Thompson   @param[out] ceed Variable to store `Ceed`
1374b7c9bbdaSJeremy L Thompson 
1375b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1376b7c9bbdaSJeremy L Thompson 
1377b7c9bbdaSJeremy L Thompson   @ref Advanced
1378b7c9bbdaSJeremy L Thompson **/
1379b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
1380b7c9bbdaSJeremy L Thompson   *ceed = rstr->ceed;
1381b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1382b7c9bbdaSJeremy L Thompson }
1383b7c9bbdaSJeremy L Thompson 
1384b7c9bbdaSJeremy L Thompson /**
1385d979a051Sjeremylt   @brief Get the L-vector component stride
1386a681ae63Sjeremylt 
1387ca94c3ddSJeremy L Thompson   @param[in]  rstr        `CeedElemRestriction`
1388d1d35e2fSjeremylt   @param[out] comp_stride Variable to store component stride
1389a681ae63Sjeremylt 
1390a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1391a681ae63Sjeremylt 
1392b7c9bbdaSJeremy L Thompson   @ref Advanced
1393a681ae63Sjeremylt **/
13942b730f8bSJeremy L Thompson int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, CeedInt *comp_stride) {
1395d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
1396e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1397a681ae63Sjeremylt }
1398a681ae63Sjeremylt 
1399a681ae63Sjeremylt /**
1400ca94c3ddSJeremy L Thompson   @brief Get the total number of elements in the range of a `CeedElemRestriction`
1401a681ae63Sjeremylt 
1402ca94c3ddSJeremy L Thompson   @param[in] rstr      `CeedElemRestriction`
1403d1d35e2fSjeremylt   @param[out] num_elem Variable to store number of elements
1404a681ae63Sjeremylt 
1405a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1406a681ae63Sjeremylt 
1407b7c9bbdaSJeremy L Thompson   @ref Advanced
1408a681ae63Sjeremylt **/
14092b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, CeedInt *num_elem) {
1410d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
1411e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1412a681ae63Sjeremylt }
1413a681ae63Sjeremylt 
1414a681ae63Sjeremylt /**
1415ca94c3ddSJeremy L Thompson   @brief Get the size of elements in the `CeedElemRestriction`
1416a681ae63Sjeremylt 
1417ca94c3ddSJeremy L Thompson   @param[in]  rstr      `CeedElemRestriction`
1418d1d35e2fSjeremylt   @param[out] elem_size Variable to store size of elements
1419a681ae63Sjeremylt 
1420a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1421a681ae63Sjeremylt 
1422b7c9bbdaSJeremy L Thompson   @ref Advanced
1423a681ae63Sjeremylt **/
14242b730f8bSJeremy L Thompson int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, CeedInt *elem_size) {
1425d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
14262c7e7413SJeremy L Thompson   return CEED_ERROR_SUCCESS;
14272c7e7413SJeremy L Thompson }
14282c7e7413SJeremy L Thompson 
14292c7e7413SJeremy L Thompson /**
143007d5dec1SJeremy L Thompson 
1431ca94c3ddSJeremy L Thompson   @brief Get the number of points in the l-vector for a points `CeedElemRestriction`
143207d5dec1SJeremy L Thompson 
1433ca94c3ddSJeremy L Thompson   @param[in]  rstr       `CeedElemRestriction`
143407d5dec1SJeremy L Thompson   @param[out] num_points The number of points in the l-vector
143507d5dec1SJeremy L Thompson 
143607d5dec1SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
143707d5dec1SJeremy L Thompson 
1438c63574e3SJeremy L Thompson   @ref User
143907d5dec1SJeremy L Thompson **/
144007d5dec1SJeremy L Thompson int CeedElemRestrictionGetNumPoints(CeedElemRestriction rstr, CeedInt *num_points) {
1441*1203703bSJeremy L Thompson   CeedRestrictionType rstr_type;
144207d5dec1SJeremy L Thompson   Ceed                ceed;
144307d5dec1SJeremy L Thompson 
144407d5dec1SJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
1445*1203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
1446*1203703bSJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, ceed, CEED_ERROR_INCOMPATIBLE,
144707d5dec1SJeremy L Thompson             "Can only retrieve the number of points for a points CeedElemRestriction");
144807d5dec1SJeremy L Thompson 
144907d5dec1SJeremy L Thompson   *num_points = rstr->num_points;
145007d5dec1SJeremy L Thompson   return CEED_ERROR_SUCCESS;
145107d5dec1SJeremy L Thompson }
145207d5dec1SJeremy L Thompson 
145307d5dec1SJeremy L Thompson /**
145407d5dec1SJeremy L Thompson 
1455ca94c3ddSJeremy L Thompson   @brief Get the number of points in an element of a `CeedElemRestriction` at points
145607d5dec1SJeremy L Thompson 
1457ca94c3ddSJeremy L Thompson   @param[in]  rstr       `CeedElemRestriction`
145807d5dec1SJeremy L Thompson   @param[in]  elem       Index number of element to retrieve the number of points for
145907d5dec1SJeremy L Thompson   @param[out] num_points The number of points in the element at index elem
146007d5dec1SJeremy L Thompson 
146107d5dec1SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
146207d5dec1SJeremy L Thompson 
1463c63574e3SJeremy L Thompson   @ref User
146407d5dec1SJeremy L Thompson **/
146507d5dec1SJeremy L Thompson int CeedElemRestrictionGetNumPointsInElement(CeedElemRestriction rstr, CeedInt elem, CeedInt *num_points) {
1466*1203703bSJeremy L Thompson   CeedRestrictionType rstr_type;
146707d5dec1SJeremy L Thompson   const CeedInt      *offsets;
1468*1203703bSJeremy L Thompson   Ceed                ceed;
146907d5dec1SJeremy L Thompson 
147007d5dec1SJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
1471*1203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
1472*1203703bSJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, ceed, CEED_ERROR_INCOMPATIBLE,
147307d5dec1SJeremy L Thompson             "Can only retrieve the number of points for a points CeedElemRestriction");
147407d5dec1SJeremy L Thompson 
147507d5dec1SJeremy L Thompson   CeedCall(CeedElemRestrictionGetOffsets(rstr, CEED_MEM_HOST, &offsets));
147607d5dec1SJeremy L Thompson   *num_points = offsets[elem + 1] - offsets[elem];
147707d5dec1SJeremy L Thompson   CeedCall(CeedElemRestrictionRestoreOffsets(rstr, &offsets));
147807d5dec1SJeremy L Thompson   return CEED_ERROR_SUCCESS;
147907d5dec1SJeremy L Thompson }
148007d5dec1SJeremy L Thompson 
148107d5dec1SJeremy L Thompson /**
1482ca94c3ddSJeremy L Thompson   @brief Get the maximum number of points in an element for a `CeedElemRestriction` at points
14832c7e7413SJeremy L Thompson 
1484ca94c3ddSJeremy L Thompson   @param[in]  rstr       `CeedElemRestriction`
14852c7e7413SJeremy L Thompson   @param[out] max_points Variable to store size of elements
14862c7e7413SJeremy L Thompson 
14872c7e7413SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
14882c7e7413SJeremy L Thompson 
14892c7e7413SJeremy L Thompson   @ref Advanced
14902c7e7413SJeremy L Thompson **/
14912c7e7413SJeremy L Thompson int CeedElemRestrictionGetMaxPointsInElement(CeedElemRestriction rstr, CeedInt *max_points) {
14922c7e7413SJeremy L Thompson   CeedInt             num_elem;
14932c7e7413SJeremy L Thompson   CeedRestrictionType rstr_type;
1494*1203703bSJeremy L Thompson   Ceed                ceed;
14952c7e7413SJeremy L Thompson 
14962c7e7413SJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
14972c7e7413SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
14982c7e7413SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, ceed, CEED_ERROR_INCOMPATIBLE,
14992c7e7413SJeremy L Thompson             "Cannot compute max points for a CeedElemRestriction that does not use points");
15002c7e7413SJeremy L Thompson 
15012c7e7413SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
15022c7e7413SJeremy L Thompson   *max_points = 0;
15032c7e7413SJeremy L Thompson   for (CeedInt e = 0; e < num_elem; e++) {
15042c7e7413SJeremy L Thompson     CeedInt num_points;
15052c7e7413SJeremy L Thompson 
15062c7e7413SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, e, &num_points));
15072c7e7413SJeremy L Thompson     *max_points = CeedIntMax(num_points, *max_points);
15082c7e7413SJeremy L Thompson   }
1509e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1510a681ae63Sjeremylt }
1511a681ae63Sjeremylt 
1512a681ae63Sjeremylt /**
1513ca94c3ddSJeremy L Thompson   @brief Get the size of the l-vector for a `CeedElemRestriction`
1514a681ae63Sjeremylt 
1515ca94c3ddSJeremy L Thompson   @param[in]  rstr   `CeedElemRestriction`
1516701e7d35SJeremy L Thompson   @param[out] l_size Variable to store l-vector size
1517a681ae63Sjeremylt 
1518a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1519a681ae63Sjeremylt 
1520b7c9bbdaSJeremy L Thompson   @ref Advanced
1521a681ae63Sjeremylt **/
15222b730f8bSJeremy L Thompson int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, CeedSize *l_size) {
1523d1d35e2fSjeremylt   *l_size = rstr->l_size;
1524e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1525a681ae63Sjeremylt }
1526a681ae63Sjeremylt 
1527a681ae63Sjeremylt /**
1528701e7d35SJeremy L Thompson   @brief Get the size of the e-vector for a `CeedElemRestriction`
1529701e7d35SJeremy L Thompson 
1530701e7d35SJeremy L Thompson   @param[in]  rstr   `CeedElemRestriction`
1531701e7d35SJeremy L Thompson   @param[out] e_size Variable to store e-vector size
1532701e7d35SJeremy L Thompson 
1533701e7d35SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1534701e7d35SJeremy L Thompson 
1535701e7d35SJeremy L Thompson   @ref Advanced
1536701e7d35SJeremy L Thompson **/
1537701e7d35SJeremy L Thompson int CeedElemRestrictionGetEVectorSize(CeedElemRestriction rstr, CeedSize *e_size) {
1538701e7d35SJeremy L Thompson   *e_size = rstr->e_size;
1539701e7d35SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1540701e7d35SJeremy L Thompson }
1541701e7d35SJeremy L Thompson 
1542701e7d35SJeremy L Thompson /**
1543ca94c3ddSJeremy L Thompson   @brief Get the number of components in the elements of a `CeedElemRestriction`
1544a681ae63Sjeremylt 
1545ca94c3ddSJeremy L Thompson   @param[in]  rstr     `CeedElemRestriction`
1546d1d35e2fSjeremylt   @param[out] num_comp Variable to store number of components
1547a681ae63Sjeremylt 
1548a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1549a681ae63Sjeremylt 
1550b7c9bbdaSJeremy L Thompson   @ref Advanced
1551a681ae63Sjeremylt **/
15522b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, CeedInt *num_comp) {
1553d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
1554e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1555a681ae63Sjeremylt }
1556a681ae63Sjeremylt 
1557a681ae63Sjeremylt /**
1558ca94c3ddSJeremy L Thompson   @brief Get the number of blocks in a `CeedElemRestriction`
1559a681ae63Sjeremylt 
1560ca94c3ddSJeremy L Thompson   @param[in]  rstr      `CeedElemRestriction`
1561d1d35e2fSjeremylt   @param[out] num_block Variable to store number of blocks
1562a681ae63Sjeremylt 
1563a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1564a681ae63Sjeremylt 
1565b7c9bbdaSJeremy L Thompson   @ref Advanced
1566a681ae63Sjeremylt **/
15672b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, CeedInt *num_block) {
1568e7f679fcSJeremy L Thompson   *num_block = rstr->num_block;
1569e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1570a681ae63Sjeremylt }
1571a681ae63Sjeremylt 
1572a681ae63Sjeremylt /**
1573ca94c3ddSJeremy L Thompson   @brief Get the size of blocks in the `CeedElemRestriction`
1574a681ae63Sjeremylt 
1575ca94c3ddSJeremy L Thompson   @param[in]  rstr       `CeedElemRestriction`
1576e7f679fcSJeremy L Thompson   @param[out] block_size Variable to store size of blocks
1577a681ae63Sjeremylt 
1578a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1579a681ae63Sjeremylt 
1580b7c9bbdaSJeremy L Thompson   @ref Advanced
1581a681ae63Sjeremylt **/
1582e7f679fcSJeremy L Thompson int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, CeedInt *block_size) {
1583e7f679fcSJeremy L Thompson   *block_size = rstr->block_size;
1584e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1585a681ae63Sjeremylt }
1586a681ae63Sjeremylt 
1587a681ae63Sjeremylt /**
1588ca94c3ddSJeremy L Thompson   @brief Get the multiplicity of nodes in a `CeedElemRestriction`
15891469ee4dSjeremylt 
1590ca94c3ddSJeremy L Thompson   @param[in]  rstr `CeedElemRestriction`
1591ca94c3ddSJeremy L Thompson   @param[out] mult Vector to store multiplicity (of size `l_size`)
15921469ee4dSjeremylt 
15931469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
15941469ee4dSjeremylt 
15957a982d89SJeremy L. Thompson   @ref User
15961469ee4dSjeremylt **/
15972b730f8bSJeremy L Thompson int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, CeedVector mult) {
1598d1d35e2fSjeremylt   CeedVector e_vec;
15991469ee4dSjeremylt 
160025509ebbSRezgar Shakeri   // Create e_vec to hold intermediate computation in E^T (E 1)
16012b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionCreateVector(rstr, NULL, &e_vec));
16021469ee4dSjeremylt 
160325509ebbSRezgar Shakeri   // Compute e_vec = E * 1
16042b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 1.0));
16052b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, CEED_REQUEST_IMMEDIATE));
160625509ebbSRezgar Shakeri   // Compute multiplicity, mult = E^T * e_vec = E^T (E 1)
16072b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 0.0));
16082b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, CEED_REQUEST_IMMEDIATE));
16091469ee4dSjeremylt   // Cleanup
16102b730f8bSJeremy L Thompson   CeedCall(CeedVectorDestroy(&e_vec));
1611e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
16121469ee4dSjeremylt }
16131469ee4dSjeremylt 
16141469ee4dSjeremylt /**
1615ca94c3ddSJeremy L Thompson   @brief View a `CeedElemRestriction`
1616f02ca4a2SJed Brown 
1617ca94c3ddSJeremy L Thompson   @param[in] rstr   `CeedElemRestriction` to view
1618ca94c3ddSJeremy L Thompson   @param[in] stream Stream to write; typically `stdout` or a file
1619f02ca4a2SJed Brown 
1620f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
1621f02ca4a2SJed Brown 
16227a982d89SJeremy L. Thompson   @ref User
1623f02ca4a2SJed Brown **/
1624f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
16250930e4e7SJeremy L Thompson   CeedRestrictionType rstr_type;
16260930e4e7SJeremy L Thompson 
16270930e4e7SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
16280930e4e7SJeremy L Thompson   if (rstr_type == CEED_RESTRICTION_POINTS) {
16290930e4e7SJeremy L Thompson     CeedInt max_points;
16300930e4e7SJeremy L Thompson 
16310930e4e7SJeremy L Thompson     CeedCall(CeedElemRestrictionGetMaxPointsInElement(rstr, &max_points));
16320930e4e7SJeremy L Thompson     fprintf(stream,
1633249f8407SJeremy L Thompson             "CeedElemRestriction at points from (%" CeedSize_FMT ", %" CeedInt_FMT ") to %" CeedInt_FMT " elements with a maximum of %" CeedInt_FMT
16340930e4e7SJeremy L Thompson             " points on an element\n",
16350930e4e7SJeremy L Thompson             rstr->l_size, rstr->num_comp, rstr->num_elem, max_points);
16360930e4e7SJeremy L Thompson   } else {
1637249f8407SJeremy L Thompson     char strides_str[500];
16381c66c397SJeremy L Thompson 
16392b730f8bSJeremy L Thompson     if (rstr->strides) {
1640249f8407SJeremy L Thompson       sprintf(strides_str, "[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "]", rstr->strides[0], rstr->strides[1], rstr->strides[2]);
16412b730f8bSJeremy L Thompson     } else {
1642249f8407SJeremy L Thompson       sprintf(strides_str, "%" CeedInt_FMT, rstr->comp_stride);
16432b730f8bSJeremy L Thompson     }
1644249f8407SJeremy L Thompson     fprintf(stream,
1645249f8407SJeremy L Thompson             "%sCeedElemRestriction from (%" CeedSize_FMT ", %" CeedInt_FMT ") to %" CeedInt_FMT " elements with %" CeedInt_FMT
1646249f8407SJeremy L Thompson             " nodes each and %s %s\n",
1647e7f679fcSJeremy L Thompson             rstr->block_size > 1 ? "Blocked " : "", rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
1648249f8407SJeremy L Thompson             rstr->strides ? "strides" : "component stride", strides_str);
16490930e4e7SJeremy L Thompson   }
1650e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1651f02ca4a2SJed Brown }
1652f02ca4a2SJed Brown 
1653f02ca4a2SJed Brown /**
1654ca94c3ddSJeremy L Thompson   @brief Destroy a `CeedElemRestriction`
1655b11c1e72Sjeremylt 
1656ca94c3ddSJeremy L Thompson   @param[in,out] rstr `CeedElemRestriction` to destroy
1657b11c1e72Sjeremylt 
1658b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1659dfdf5a53Sjeremylt 
16607a982d89SJeremy L. Thompson   @ref User
1661b11c1e72Sjeremylt **/
16624ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
1663393ac2cdSJeremy L Thompson   if (!*rstr || *rstr == CEED_ELEMRESTRICTION_NONE || --(*rstr)->ref_count > 0) {
1664ad6481ceSJeremy L Thompson     *rstr = NULL;
1665ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
1666ad6481ceSJeremy L Thompson   }
16676574a04fSJeremy L Thompson   CeedCheck((*rstr)->num_readers == 0, (*rstr)->ceed, CEED_ERROR_ACCESS,
16686574a04fSJeremy L Thompson             "Cannot destroy CeedElemRestriction, a process has read access to the offset data");
1669c17ec2beSJeremy L Thompson 
1670c17ec2beSJeremy L Thompson   // Only destroy backend data once between rstr and unsigned copy
16717c1dbaffSSebastian Grimberg   if ((*rstr)->rstr_base) CeedCall(CeedElemRestrictionDestroy(&(*rstr)->rstr_base));
1672c17ec2beSJeremy L Thompson   else if ((*rstr)->Destroy) CeedCall((*rstr)->Destroy(*rstr));
1673c17ec2beSJeremy L Thompson 
16742b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*rstr)->strides));
16752b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*rstr)->ceed));
16762b730f8bSJeremy L Thompson   CeedCall(CeedFree(rstr));
1677e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1678d7b241e6Sjeremylt }
1679d7b241e6Sjeremylt 
1680d7b241e6Sjeremylt /// @}
1681