xref: /libCEED/interface/ceed-elemrestriction.c (revision 9bc663991d6482bcb1d60b1f116148f11db83fa1)
15aed82e4SJeremy L Thompson // Copyright (c) 2017-2024, Lawrence Livermore National Security, LLC and other CEED contributors.
23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3d7b241e6Sjeremylt //
43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
5d7b241e6Sjeremylt //
63d8e8822SJeremy L Thompson // This file is part of CEED:  http://github.com/ceed
7d7b241e6Sjeremylt 
83d576824SJeremy L Thompson #include <ceed-impl.h>
949aac155SJeremy L Thompson #include <ceed.h>
102b730f8bSJeremy L Thompson #include <ceed/backend.h>
113d576824SJeremy L Thompson #include <stdbool.h>
123d576824SJeremy L Thompson #include <stdio.h>
13c17ec2beSJeremy L Thompson #include <string.h>
14d7b241e6Sjeremylt 
157a982d89SJeremy L. Thompson /// @file
167a982d89SJeremy L. Thompson /// Implementation of CeedElemRestriction interfaces
177a982d89SJeremy L. Thompson 
187a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
197a982d89SJeremy L. Thompson /// CeedElemRestriction Library Internal Functions
207a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
217a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionDeveloper
227a982d89SJeremy L. Thompson /// @{
237a982d89SJeremy L. Thompson 
247a982d89SJeremy L. Thompson /**
25ca94c3ddSJeremy L Thompson   @brief Permute and pad offsets for a blocked `CeedElemRestriction`
267a982d89SJeremy L. Thompson 
27ca94c3ddSJeremy L Thompson   @param[in]  offsets       Array of shape `[num_elem, elem_size]`
28ca94c3ddSJeremy L Thompson   @param[out] block_offsets Array of permuted and padded array values of shape `[num_block, elem_size, block_size]`
29e7f679fcSJeremy L Thompson   @param[in]  num_block     Number of blocks
30ea61e9acSJeremy L Thompson   @param[in]  num_elem      Number of elements
31e7f679fcSJeremy L Thompson   @param[in]  block_size    Number of elements in a block
32ea61e9acSJeremy L Thompson   @param[in]  elem_size     Size of each element
337a982d89SJeremy L. Thompson 
347a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
357a982d89SJeremy L. Thompson 
367a982d89SJeremy L. Thompson   @ref Utility
377a982d89SJeremy L. Thompson **/
38e7f679fcSJeremy L Thompson int CeedPermutePadOffsets(const CeedInt *offsets, CeedInt *block_offsets, CeedInt num_block, CeedInt num_elem, CeedInt block_size,
39e7f679fcSJeremy L Thompson                           CeedInt elem_size) {
40e7f679fcSJeremy L Thompson   for (CeedInt e = 0; e < num_block * block_size; e += block_size) {
41e7f679fcSJeremy L Thompson     for (CeedInt j = 0; j < block_size; j++) {
422b730f8bSJeremy L Thompson       for (CeedInt k = 0; k < elem_size; k++) {
43e7f679fcSJeremy L Thompson         block_offsets[e * elem_size + k * block_size + j] = offsets[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
442b730f8bSJeremy L Thompson       }
452b730f8bSJeremy L Thompson     }
462b730f8bSJeremy L Thompson   }
47e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
487a982d89SJeremy L. Thompson }
497a982d89SJeremy L. Thompson 
5077d1c127SSebastian Grimberg /**
51ca94c3ddSJeremy L Thompson   @brief Permute and pad orientations for a blocked `CeedElemRestriction`
5277d1c127SSebastian Grimberg 
53ca94c3ddSJeremy L Thompson   @param[in]  orients       Array of shape `[num_elem, elem_size]`
54ca94c3ddSJeremy L Thompson   @param[out] block_orients Array of permuted and padded array values of shape `[num_block, elem_size, block_size]`
55e7f679fcSJeremy L Thompson   @param[in]  num_block     Number of blocks
5677d1c127SSebastian Grimberg   @param[in]  num_elem      Number of elements
57e7f679fcSJeremy L Thompson   @param[in]  block_size    Number of elements in a block
5877d1c127SSebastian Grimberg   @param[in]  elem_size     Size of each element
5977d1c127SSebastian Grimberg 
6077d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
6177d1c127SSebastian Grimberg 
6277d1c127SSebastian Grimberg   @ref Utility
6377d1c127SSebastian Grimberg **/
64e7f679fcSJeremy L Thompson int CeedPermutePadOrients(const bool *orients, bool *block_orients, CeedInt num_block, CeedInt num_elem, CeedInt block_size, CeedInt elem_size) {
65e7f679fcSJeremy L Thompson   for (CeedInt e = 0; e < num_block * block_size; e += block_size) {
66e7f679fcSJeremy L Thompson     for (CeedInt j = 0; j < block_size; j++) {
6777d1c127SSebastian Grimberg       for (CeedInt k = 0; k < elem_size; k++) {
68e7f679fcSJeremy L Thompson         block_orients[e * elem_size + k * block_size + j] = orients[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
6977d1c127SSebastian Grimberg       }
7077d1c127SSebastian Grimberg     }
7177d1c127SSebastian Grimberg   }
7277d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
7377d1c127SSebastian Grimberg }
7477d1c127SSebastian Grimberg 
750c73c039SSebastian Grimberg /**
76ca94c3ddSJeremy L Thompson   @brief Permute and pad curl-conforming orientations for a blocked `CeedElemRestriction`
770c73c039SSebastian Grimberg 
785c7e0f51SSebastian Grimberg   @param[in]  curl_orients       Array of shape `[num_elem, elem_size]`
79ca94c3ddSJeremy L Thompson   @param[out] block_curl_orients Array of permuted and padded array values of shape `[num_block, elem_size, block_size]`
80e7f679fcSJeremy L Thompson   @param[in]  num_block          Number of blocks
810c73c039SSebastian Grimberg   @param[in]  num_elem           Number of elements
82e7f679fcSJeremy L Thompson   @param[in]  block_size         Number of elements in a block
830c73c039SSebastian Grimberg   @param[in]  elem_size          Size of each element
840c73c039SSebastian Grimberg 
850c73c039SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
860c73c039SSebastian Grimberg 
870c73c039SSebastian Grimberg   @ref Utility
880c73c039SSebastian Grimberg **/
89e7f679fcSJeremy L Thompson int CeedPermutePadCurlOrients(const CeedInt8 *curl_orients, CeedInt8 *block_curl_orients, CeedInt num_block, CeedInt num_elem, CeedInt block_size,
900c73c039SSebastian Grimberg                               CeedInt elem_size) {
91e7f679fcSJeremy L Thompson   for (CeedInt e = 0; e < num_block * block_size; e += block_size) {
92e7f679fcSJeremy L Thompson     for (CeedInt j = 0; j < block_size; j++) {
930c73c039SSebastian Grimberg       for (CeedInt k = 0; k < elem_size; k++) {
94e7f679fcSJeremy L Thompson         block_curl_orients[e * elem_size + k * block_size + j] = curl_orients[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
950c73c039SSebastian Grimberg       }
960c73c039SSebastian Grimberg     }
970c73c039SSebastian Grimberg   }
980c73c039SSebastian Grimberg   return CEED_ERROR_SUCCESS;
990c73c039SSebastian Grimberg }
1000c73c039SSebastian Grimberg 
1017a982d89SJeremy L. Thompson /// @}
1027a982d89SJeremy L. Thompson 
1037a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1047a982d89SJeremy L. Thompson /// CeedElemRestriction Backend API
1057a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1067a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionBackend
1077a982d89SJeremy L. Thompson /// @{
1087a982d89SJeremy L. Thompson 
1097a982d89SJeremy L. Thompson /**
110ca94c3ddSJeremy L Thompson   @brief Get the type of a `CeedElemRestriction`
111a681ae63Sjeremylt 
112ca94c3ddSJeremy L Thompson   @param[in]  rstr      `CeedElemRestriction`
113fcbe8c06SSebastian Grimberg   @param[out] rstr_type Variable to store restriction type
114fcbe8c06SSebastian Grimberg 
115fcbe8c06SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
116fcbe8c06SSebastian Grimberg 
117fcbe8c06SSebastian Grimberg   @ref Backend
118fcbe8c06SSebastian Grimberg **/
119fcbe8c06SSebastian Grimberg int CeedElemRestrictionGetType(CeedElemRestriction rstr, CeedRestrictionType *rstr_type) {
120fcbe8c06SSebastian Grimberg   *rstr_type = rstr->rstr_type;
121fcbe8c06SSebastian Grimberg   return CEED_ERROR_SUCCESS;
122fcbe8c06SSebastian Grimberg }
123fcbe8c06SSebastian Grimberg 
124fcbe8c06SSebastian Grimberg /**
125ca94c3ddSJeremy L Thompson   @brief Get the strided status of a `CeedElemRestriction`
126fcbe8c06SSebastian Grimberg 
127ca94c3ddSJeremy L Thompson   @param[in]  rstr       `CeedElemRestriction`
128ca94c3ddSJeremy L Thompson   @param[out] is_strided Variable to store strided status
129ca94c3ddSJeremy L Thompson 
130ca94c3ddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
131ca94c3ddSJeremy L Thompson 
132ca94c3ddSJeremy L Thompson   @ref Backend
133fcbe8c06SSebastian Grimberg **/
134fcbe8c06SSebastian Grimberg int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) {
135fcbe8c06SSebastian Grimberg   *is_strided = (rstr->rstr_type == CEED_RESTRICTION_STRIDED);
136fcbe8c06SSebastian Grimberg   return CEED_ERROR_SUCCESS;
137fcbe8c06SSebastian Grimberg }
138fcbe8c06SSebastian Grimberg 
139fcbe8c06SSebastian Grimberg /**
140ca94c3ddSJeremy L Thompson   @brief Get the points status of a `CeedElemRestriction`
1413ac8f562SJeremy L Thompson 
142ca94c3ddSJeremy L Thompson   @param[in]  rstr      `CeedElemRestriction`
143ca94c3ddSJeremy L Thompson   @param[out] is_points Variable to store points status
144ca94c3ddSJeremy L Thompson 
145ca94c3ddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
146ca94c3ddSJeremy L Thompson 
147ca94c3ddSJeremy L Thompson   @ref Backend
1483ac8f562SJeremy L Thompson **/
149637baffdSJeremy L Thompson int CeedElemRestrictionIsAtPoints(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;
16748acf710SJeremy L Thompson 
16848acf710SJeremy L Thompson   // Cannot compare non-points restrictions
169*9bc66399SJeremy L Thompson   CeedCheck(rstr_a->rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr_a), CEED_ERROR_UNSUPPORTED,
170*9bc66399SJeremy L Thompson             "First CeedElemRestriction must be AtPoints");
171*9bc66399SJeremy L Thompson   CeedCheck(rstr_b->rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr_a), CEED_ERROR_UNSUPPORTED,
172*9bc66399SJeremy L Thompson             "Second CeedElemRestriction must be AtPoints");
17348acf710SJeremy L Thompson 
17448acf710SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr_a, &num_elem_a));
17548acf710SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr_b, &num_elem_b));
17648acf710SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumPoints(rstr_a, &num_points_a));
17748acf710SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumPoints(rstr_b, &num_points_b));
17848acf710SJeremy L Thompson 
17948acf710SJeremy L Thompson   // Check size and contents of offsets arrays
18048acf710SJeremy L Thompson   *are_compatible = true;
18148acf710SJeremy L Thompson   if (num_elem_a != num_elem_b) *are_compatible = false;
18248acf710SJeremy L Thompson   if (num_points_a != num_points_b) *are_compatible = false;
18348acf710SJeremy L Thompson   if (*are_compatible) {
18448acf710SJeremy L Thompson     const CeedInt *offsets_a, *offsets_b;
18548acf710SJeremy L Thompson 
18648acf710SJeremy L Thompson     CeedCall(CeedElemRestrictionGetOffsets(rstr_a, CEED_MEM_HOST, &offsets_a));
18748acf710SJeremy L Thompson     CeedCall(CeedElemRestrictionGetOffsets(rstr_b, CEED_MEM_HOST, &offsets_b));
18848acf710SJeremy L Thompson     for (CeedInt i = 0; i < num_elem_a + 1 + num_points_a; i++) *are_compatible &= offsets_a[i] == offsets_b[i];
18948acf710SJeremy L Thompson     CeedCall(CeedElemRestrictionRestoreOffsets(rstr_a, &offsets_a));
19048acf710SJeremy L Thompson     CeedCall(CeedElemRestrictionRestoreOffsets(rstr_b, &offsets_b));
19148acf710SJeremy L Thompson   }
19248acf710SJeremy L Thompson   return CEED_ERROR_SUCCESS;
19348acf710SJeremy L Thompson }
19448acf710SJeremy L Thompson 
19548acf710SJeremy L Thompson /**
196ca94c3ddSJeremy L Thompson   @brief Get the strides of a strided `CeedElemRestriction`
1977a982d89SJeremy L. Thompson 
198ca94c3ddSJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
199a681ae63Sjeremylt   @param[out] strides Variable to store strides array
2007a982d89SJeremy L. Thompson 
2017a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2027a982d89SJeremy L. Thompson 
2037a982d89SJeremy L. Thompson   @ref Backend
2047a982d89SJeremy L. Thompson **/
20556c48462SJeremy L Thompson int CeedElemRestrictionGetStrides(CeedElemRestriction rstr, CeedInt strides[3]) {
2066e536b99SJeremy L Thompson   CeedCheck(rstr->strides, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, "CeedElemRestriction has no stride data");
20756c48462SJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) strides[i] = rstr->strides[i];
208e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2097a982d89SJeremy L. Thompson }
2107a982d89SJeremy L. Thompson 
2117a982d89SJeremy L. Thompson /**
212ca94c3ddSJeremy L Thompson   @brief Get the backend stride status of a `CeedElemRestriction`
21377d1c127SSebastian Grimberg 
214ca94c3ddSJeremy L Thompson   @param[in]  rstr                 `CeedElemRestriction`
21577d1c127SSebastian Grimberg   @param[out] has_backend_strides  Variable to store stride status
21677d1c127SSebastian Grimberg 
21777d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
21877d1c127SSebastian Grimberg 
21977d1c127SSebastian Grimberg   @ref Backend
22077d1c127SSebastian Grimberg **/
22177d1c127SSebastian Grimberg int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, bool *has_backend_strides) {
2226e536b99SJeremy L Thompson   CeedCheck(rstr->strides, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, "CeedElemRestriction has no stride data");
22377d1c127SSebastian Grimberg   *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
22477d1c127SSebastian Grimberg                           (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
22577d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
22677d1c127SSebastian Grimberg }
22777d1c127SSebastian Grimberg 
22877d1c127SSebastian Grimberg /**
229ca94c3ddSJeremy L Thompson   @brief Get read-only access to a `CeedElemRestriction` offsets array by @ref CeedMemType
230bd33150aSjeremylt 
231ca94c3ddSJeremy L Thompson   @param[in]  rstr     `CeedElemRestriction` to retrieve offsets
232fcbe8c06SSebastian Grimberg   @param[in]  mem_type Memory type on which to access the array.
233fcbe8c06SSebastian Grimberg                          If the backend uses a different memory type, this will perform a copy (possibly cached).
234ca94c3ddSJeremy L Thompson   @param[out] offsets  Array on memory type `mem_type`
235bd33150aSjeremylt 
236bd33150aSjeremylt   @return An error code: 0 - success, otherwise - failure
237bd33150aSjeremylt 
238bd33150aSjeremylt   @ref User
239bd33150aSjeremylt **/
2402b730f8bSJeremy L Thompson int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) {
2417c1dbaffSSebastian Grimberg   if (rstr->rstr_base) {
2427c1dbaffSSebastian Grimberg     CeedCall(CeedElemRestrictionGetOffsets(rstr->rstr_base, mem_type, offsets));
243c17ec2beSJeremy L Thompson   } else {
2446e536b99SJeremy L Thompson     CeedCheck(rstr->GetOffsets, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED,
2451ef3a2a9SJeremy L Thompson               "Backend does not implement CeedElemRestrictionGetOffsets");
2462b730f8bSJeremy L Thompson     CeedCall(rstr->GetOffsets(rstr, mem_type, offsets));
247d1d35e2fSjeremylt     rstr->num_readers++;
248c17ec2beSJeremy L Thompson   }
249e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
250430758c8SJeremy L Thompson }
251430758c8SJeremy L Thompson 
252430758c8SJeremy L Thompson /**
253ca94c3ddSJeremy L Thompson   @brief Restore an offsets array obtained using @ref CeedElemRestrictionGetOffsets()
254430758c8SJeremy L Thompson 
255ca94c3ddSJeremy L Thompson   @param[in] rstr    `CeedElemRestriction` to restore
256ea61e9acSJeremy L Thompson   @param[in] offsets Array of offset data
257430758c8SJeremy L Thompson 
258430758c8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
259430758c8SJeremy L Thompson 
260430758c8SJeremy L Thompson   @ref User
261430758c8SJeremy L Thompson **/
2622b730f8bSJeremy L Thompson int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr, const CeedInt **offsets) {
2637c1dbaffSSebastian Grimberg   if (rstr->rstr_base) {
2647c1dbaffSSebastian Grimberg     CeedCall(CeedElemRestrictionRestoreOffsets(rstr->rstr_base, offsets));
265c17ec2beSJeremy L Thompson   } else {
266430758c8SJeremy L Thompson     *offsets = NULL;
267d1d35e2fSjeremylt     rstr->num_readers--;
268c17ec2beSJeremy L Thompson   }
269e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
270bd33150aSjeremylt }
271bd33150aSjeremylt 
272bd33150aSjeremylt /**
273ca94c3ddSJeremy L Thompson   @brief Get read-only access to a `CeedElemRestriction` orientations array by @ref CeedMemType
2743ac43b2cSJeremy L Thompson 
275ca94c3ddSJeremy L Thompson   @param[in]  rstr     `CeedElemRestriction` to retrieve orientations
276fcbe8c06SSebastian Grimberg   @param[in]  mem_type Memory type on which to access the array.
277fcbe8c06SSebastian Grimberg                          If the backend uses a different memory type, this will perform a copy (possibly cached).
278ca94c3ddSJeremy L Thompson   @param[out] orients  Array on memory type `mem_type`
2793ac43b2cSJeremy L Thompson 
2803ac43b2cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2813ac43b2cSJeremy L Thompson 
28277d1c127SSebastian Grimberg   @ref User
2833ac43b2cSJeremy L Thompson **/
28477d1c127SSebastian Grimberg int CeedElemRestrictionGetOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const bool **orients) {
2856e536b99SJeremy L Thompson   CeedCheck(rstr->GetOrientations, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED,
2861ef3a2a9SJeremy L Thompson             "Backend does not implement CeedElemRestrictionGetOrientations");
28777d1c127SSebastian Grimberg   CeedCall(rstr->GetOrientations(rstr, mem_type, orients));
28877d1c127SSebastian Grimberg   rstr->num_readers++;
289e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2903ac43b2cSJeremy L Thompson }
2913ac43b2cSJeremy L Thompson 
2923ac43b2cSJeremy L Thompson /**
293ca94c3ddSJeremy L Thompson   @brief Restore an orientations array obtained using @ref CeedElemRestrictionGetOrientations()
294b435c5a6Srezgarshakeri 
295ca94c3ddSJeremy L Thompson   @param[in] rstr    `CeedElemRestriction` to restore
29677d1c127SSebastian Grimberg   @param[in] orients Array of orientation data
297b435c5a6Srezgarshakeri 
298b435c5a6Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
299b435c5a6Srezgarshakeri 
30077d1c127SSebastian Grimberg   @ref User
301b435c5a6Srezgarshakeri **/
30277d1c127SSebastian Grimberg int CeedElemRestrictionRestoreOrientations(CeedElemRestriction rstr, const bool **orients) {
30377d1c127SSebastian Grimberg   *orients = NULL;
30477d1c127SSebastian Grimberg   rstr->num_readers--;
305b435c5a6Srezgarshakeri   return CEED_ERROR_SUCCESS;
306b435c5a6Srezgarshakeri }
307b435c5a6Srezgarshakeri 
308b435c5a6Srezgarshakeri /**
309ca94c3ddSJeremy L Thompson   @brief Get read-only access to a `CeedElemRestriction` curl-conforming orientations array by @ref CeedMemType
3107a982d89SJeremy L. Thompson 
311ca94c3ddSJeremy L Thompson   @param[in]  rstr         `CeedElemRestriction` to retrieve curl-conforming orientations
312fcbe8c06SSebastian Grimberg   @param[in]  mem_type     Memory type on which to access the array.
313fcbe8c06SSebastian Grimberg                              If the backend uses a different memory type, this will perform a copy (possibly cached).
314ca94c3ddSJeremy L Thompson   @param[out] curl_orients Array on memory type `mem_type`
3157a982d89SJeremy L. Thompson 
3167a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3177a982d89SJeremy L. Thompson 
31877d1c127SSebastian Grimberg   @ref User
3197a982d89SJeremy L. Thompson **/
3200c73c039SSebastian Grimberg int CeedElemRestrictionGetCurlOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt8 **curl_orients) {
3216e536b99SJeremy L Thompson   CeedCheck(rstr->GetCurlOrientations, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED,
3221ef3a2a9SJeremy L Thompson             "Backend does not implement CeedElemRestrictionGetCurlOrientations");
32377d1c127SSebastian Grimberg   CeedCall(rstr->GetCurlOrientations(rstr, mem_type, curl_orients));
32477d1c127SSebastian Grimberg   rstr->num_readers++;
32577d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
32677d1c127SSebastian Grimberg }
32777d1c127SSebastian Grimberg 
32877d1c127SSebastian Grimberg /**
329ca94c3ddSJeremy L Thompson   @brief Restore an orientations array obtained using @ref CeedElemRestrictionGetCurlOrientations()
33077d1c127SSebastian Grimberg 
331ca94c3ddSJeremy L Thompson   @param[in] rstr         `CeedElemRestriction` to restore
33277d1c127SSebastian Grimberg   @param[in] curl_orients Array of orientation data
33377d1c127SSebastian Grimberg 
33477d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
33577d1c127SSebastian Grimberg 
33677d1c127SSebastian Grimberg   @ref User
33777d1c127SSebastian Grimberg **/
3380c73c039SSebastian Grimberg int CeedElemRestrictionRestoreCurlOrientations(CeedElemRestriction rstr, const CeedInt8 **curl_orients) {
33977d1c127SSebastian Grimberg   *curl_orients = NULL;
34077d1c127SSebastian Grimberg   rstr->num_readers--;
341e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3427a982d89SJeremy L. Thompson }
3437a982d89SJeremy L. Thompson 
3447a982d89SJeremy L. Thompson /**
34549fd234cSJeremy L Thompson 
34622eb1385SJeremy L Thompson   @brief Get the L-vector layout of a strided `CeedElemRestriction`
34722eb1385SJeremy L Thompson 
34822eb1385SJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
34922eb1385SJeremy L Thompson   @param[out] layout  Variable to store layout array, stored as `[nodes, components, elements]`.
35022eb1385SJeremy 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]`.
35122eb1385SJeremy L Thompson 
35222eb1385SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
35322eb1385SJeremy L Thompson 
35422eb1385SJeremy L Thompson   @ref Backend
35522eb1385SJeremy L Thompson **/
35656c48462SJeremy L Thompson int CeedElemRestrictionGetLLayout(CeedElemRestriction rstr, CeedInt layout[3]) {
35722eb1385SJeremy L Thompson   bool                has_backend_strides;
35822eb1385SJeremy L Thompson   CeedRestrictionType rstr_type;
35922eb1385SJeremy L Thompson 
36022eb1385SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
361*9bc66399SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_STRIDED, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR,
362*9bc66399SJeremy L Thompson             "Only strided CeedElemRestriction have strided L-vector layout");
36322eb1385SJeremy L Thompson   CeedCall(CeedElemRestrictionHasBackendStrides(rstr, &has_backend_strides));
36422eb1385SJeremy L Thompson   if (has_backend_strides) {
365*9bc66399SJeremy L Thompson     CeedCheck(rstr->l_layout[0], CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, "CeedElemRestriction has no L-vector layout data");
36656c48462SJeremy L Thompson     for (CeedInt i = 0; i < 3; i++) layout[i] = rstr->l_layout[i];
36722eb1385SJeremy L Thompson   } else {
36822eb1385SJeremy L Thompson     CeedCall(CeedElemRestrictionGetStrides(rstr, layout));
36922eb1385SJeremy L Thompson   }
37022eb1385SJeremy L Thompson   return CEED_ERROR_SUCCESS;
37122eb1385SJeremy L Thompson }
37222eb1385SJeremy L Thompson 
37322eb1385SJeremy L Thompson /**
37422eb1385SJeremy L Thompson 
37522eb1385SJeremy L Thompson   @brief Set the L-vector layout of a strided `CeedElemRestriction`
37622eb1385SJeremy L Thompson 
37722eb1385SJeremy L Thompson   @param[in] rstr   `CeedElemRestriction`
37822eb1385SJeremy L Thompson   @param[in] layout Variable to containing layout array, stored as `[nodes, components, elements]`.
37922eb1385SJeremy 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]`.
38022eb1385SJeremy L Thompson 
38122eb1385SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
38222eb1385SJeremy L Thompson 
38322eb1385SJeremy L Thompson   @ref Backend
38422eb1385SJeremy L Thompson **/
38522eb1385SJeremy L Thompson int CeedElemRestrictionSetLLayout(CeedElemRestriction rstr, CeedInt layout[3]) {
38622eb1385SJeremy L Thompson   CeedRestrictionType rstr_type;
38722eb1385SJeremy L Thompson 
38822eb1385SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
3896e536b99SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_STRIDED, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR,
3906e536b99SJeremy L Thompson             "Only strided CeedElemRestriction have strided L-vector layout");
39122eb1385SJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) rstr->l_layout[i] = layout[i];
39222eb1385SJeremy L Thompson   return CEED_ERROR_SUCCESS;
39322eb1385SJeremy L Thompson }
39422eb1385SJeremy L Thompson 
39522eb1385SJeremy L Thompson /**
39622eb1385SJeremy L Thompson 
397ca94c3ddSJeremy L Thompson   @brief Get the E-vector layout of a `CeedElemRestriction`
39849fd234cSJeremy L Thompson 
399ca94c3ddSJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
400ca94c3ddSJeremy L Thompson   @param[out] layout  Variable to store layout array, stored as `[nodes, components, elements]`.
401ca94c3ddSJeremy 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]`.
40249fd234cSJeremy L Thompson 
40349fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
40449fd234cSJeremy L Thompson 
40549fd234cSJeremy L Thompson   @ref Backend
40649fd234cSJeremy L Thompson **/
40756c48462SJeremy L Thompson int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
4086e536b99SJeremy L Thompson   CeedCheck(rstr->e_layout[0], CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, "CeedElemRestriction has no E-vector layout data");
40956c48462SJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) layout[i] = rstr->e_layout[i];
410e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
41149fd234cSJeremy L Thompson }
41249fd234cSJeremy L Thompson 
41349fd234cSJeremy L Thompson /**
41449fd234cSJeremy L Thompson 
415ca94c3ddSJeremy L Thompson   @brief Set the E-vector layout of a `CeedElemRestriction`
41649fd234cSJeremy L Thompson 
417ca94c3ddSJeremy L Thompson   @param[in] rstr   `CeedElemRestriction`
418ca94c3ddSJeremy L Thompson   @param[in] layout Variable to containing layout array, stored as `[nodes, components, elements]`.
419ca94c3ddSJeremy 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]`.
42049fd234cSJeremy L Thompson 
42149fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
42249fd234cSJeremy L Thompson 
42349fd234cSJeremy L Thompson   @ref Backend
42449fd234cSJeremy L Thompson **/
4252b730f8bSJeremy L Thompson int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
42622eb1385SJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) rstr->e_layout[i] = layout[i];
427e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
42849fd234cSJeremy L Thompson }
42949fd234cSJeremy L Thompson 
43049fd234cSJeremy L Thompson /**
43119605835SJeremy L Thompson 
43219605835SJeremy L Thompson   @brief Get the E-vector element offset of a `CeedElemRestriction` at points
43319605835SJeremy L Thompson 
43419605835SJeremy L Thompson   @param[in]  rstr        `CeedElemRestriction`
43519605835SJeremy L Thompson   @param[in]  elem        Element number index into E-vector for
43619605835SJeremy L Thompson   @param[out] elem_offset Offset for element `elem` in the E-vector.
43719605835SJeremy L Thompson                             The data for point `i`, component `j`, element `elem` in the E-vector is given by `i*e_layout[0] + j*e_layout[1] + elem_offset`.
43819605835SJeremy L Thompson 
43919605835SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
44019605835SJeremy L Thompson 
44119605835SJeremy L Thompson   @ref Backend
44219605835SJeremy L Thompson **/
44319605835SJeremy L Thompson int CeedElemRestrictionGetAtPointsElementOffset(CeedElemRestriction rstr, CeedInt elem, CeedSize *elem_offset) {
44419605835SJeremy L Thompson   CeedInt             num_comp;
44519605835SJeremy L Thompson   CeedRestrictionType rstr_type;
44619605835SJeremy L Thompson 
44719605835SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
44819605835SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
44919605835SJeremy L Thompson             "Can only compute offset for a points CeedElemRestriction");
45019605835SJeremy L Thompson 
45119605835SJeremy L Thompson   // Backend method
45219605835SJeremy L Thompson   if (rstr->GetAtPointsElementOffset) {
45319605835SJeremy L Thompson     CeedCall(rstr->GetAtPointsElementOffset(rstr, elem, elem_offset));
45419605835SJeremy L Thompson     return CEED_ERROR_SUCCESS;
45519605835SJeremy L Thompson   }
45619605835SJeremy L Thompson 
45719605835SJeremy L Thompson   // Default layout (CPU)
45819605835SJeremy L Thompson   *elem_offset = 0;
45919605835SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
46019605835SJeremy L Thompson   for (CeedInt i = 0; i < elem; i++) {
46119605835SJeremy L Thompson     CeedInt num_points;
46219605835SJeremy L Thompson 
46319605835SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, i, &num_points));
46419605835SJeremy L Thompson     *elem_offset += num_points * num_comp;
46519605835SJeremy L Thompson   }
46619605835SJeremy L Thompson   return CEED_ERROR_SUCCESS;
46719605835SJeremy L Thompson }
46819605835SJeremy L Thompson 
46919605835SJeremy L Thompson /**
470ff1bc20eSJeremy L Thompson 
471ff1bc20eSJeremy L Thompson   @brief Set the E-vector size of a `CeedElemRestriction` at points
472ff1bc20eSJeremy L Thompson 
473ff1bc20eSJeremy L Thompson   @param[in,out]  rstr   `CeedElemRestriction`
474ff1bc20eSJeremy L Thompson   @param[in]      e_size New E-vector size; must be longer than the current E-vector size
475ff1bc20eSJeremy L Thompson 
476ff1bc20eSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
477ff1bc20eSJeremy L Thompson 
478ff1bc20eSJeremy L Thompson   @ref Backend
479ff1bc20eSJeremy L Thompson **/
480ff1bc20eSJeremy L Thompson int CeedElemRestrictionSetAtPointsEVectorSize(CeedElemRestriction rstr, CeedSize e_size) {
481ff1bc20eSJeremy L Thompson   CeedRestrictionType rstr_type;
482ff1bc20eSJeremy L Thompson 
483ff1bc20eSJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
484*9bc66399SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
485*9bc66399SJeremy L Thompson             "Can only compute offset for a points CeedElemRestriction");
486*9bc66399SJeremy L Thompson   CeedCheck(e_size >= rstr->e_size, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
4873f08121cSJeremy L Thompson             "Can only increase the size of the E-vector for the CeedElemRestriction."
4883f08121cSJeremy L Thompson             " Current size: %" CeedSize_FMT " New size: %" CeedSize_FMT,
4893f08121cSJeremy L Thompson             rstr->e_size, e_size);
490ff1bc20eSJeremy L Thompson   rstr->e_size = e_size;
491ff1bc20eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
492ff1bc20eSJeremy L Thompson }
493ff1bc20eSJeremy L Thompson 
494ff1bc20eSJeremy L Thompson /**
495ca94c3ddSJeremy L Thompson   @brief Get the backend data of a `CeedElemRestriction`
4967a982d89SJeremy L. Thompson 
497ca94c3ddSJeremy L Thompson   @param[in]  rstr `CeedElemRestriction`
4987a982d89SJeremy L. Thompson   @param[out] data Variable to store data
4997a982d89SJeremy L. Thompson 
5007a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
5017a982d89SJeremy L. Thompson 
5027a982d89SJeremy L. Thompson   @ref Backend
5037a982d89SJeremy L. Thompson **/
504777ff853SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) {
505777ff853SJeremy L Thompson   *(void **)data = rstr->data;
506e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5077a982d89SJeremy L. Thompson }
5087a982d89SJeremy L. Thompson 
5097a982d89SJeremy L. Thompson /**
510ca94c3ddSJeremy L Thompson   @brief Set the backend data of a `CeedElemRestriction`
5117a982d89SJeremy L. Thompson 
512ca94c3ddSJeremy L Thompson   @param[in,out] rstr `CeedElemRestriction`
513ea61e9acSJeremy L Thompson   @param[in]     data Data to set
5147a982d89SJeremy L. Thompson 
5157a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
5167a982d89SJeremy L. Thompson 
5177a982d89SJeremy L. Thompson   @ref Backend
5187a982d89SJeremy L. Thompson **/
519777ff853SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) {
520777ff853SJeremy L Thompson   rstr->data = data;
521e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5227a982d89SJeremy L. Thompson }
5237a982d89SJeremy L. Thompson 
52434359f16Sjeremylt /**
525ca94c3ddSJeremy L Thompson   @brief Increment the reference counter for a `CeedElemRestriction`
52634359f16Sjeremylt 
527ca94c3ddSJeremy L Thompson   @param[in,out] rstr `CeedElemRestriction` to increment the reference counter
52834359f16Sjeremylt 
52934359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
53034359f16Sjeremylt 
53134359f16Sjeremylt   @ref Backend
53234359f16Sjeremylt **/
5339560d06aSjeremylt int CeedElemRestrictionReference(CeedElemRestriction rstr) {
53434359f16Sjeremylt   rstr->ref_count++;
53534359f16Sjeremylt   return CEED_ERROR_SUCCESS;
53634359f16Sjeremylt }
53734359f16Sjeremylt 
5386e15d496SJeremy L Thompson /**
539ca94c3ddSJeremy L Thompson   @brief Estimate number of FLOPs required to apply `CeedElemRestriction` in `t_mode`
5406e15d496SJeremy L Thompson 
541ca94c3ddSJeremy L Thompson   @param[in]  rstr   `CeedElemRestriction` to estimate FLOPs for
542ea61e9acSJeremy L Thompson   @param[in]  t_mode Apply restriction or transpose
543ea61e9acSJeremy L Thompson   @param[out] flops  Address of variable to hold FLOPs estimate
5446e15d496SJeremy L Thompson 
5456e15d496SJeremy L Thompson   @ref Backend
5466e15d496SJeremy L Thompson **/
5472b730f8bSJeremy L Thompson int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedSize *flops) {
5481203703bSJeremy L Thompson   CeedSize            e_size, scale = 0;
54989edb9e3SSebastian Grimberg   CeedRestrictionType rstr_type;
5501c66c397SJeremy L Thompson 
5511203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &e_size));
55289edb9e3SSebastian Grimberg   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
55377d1c127SSebastian Grimberg   if (t_mode == CEED_TRANSPOSE) {
55489edb9e3SSebastian Grimberg     switch (rstr_type) {
5553ac8f562SJeremy L Thompson       case CEED_RESTRICTION_POINTS:
5563ac8f562SJeremy L Thompson         scale = 0;
5573ac8f562SJeremy L Thompson         break;
55889edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STRIDED:
55989edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STANDARD:
56077d1c127SSebastian Grimberg         scale = 1;
56189edb9e3SSebastian Grimberg         break;
56289edb9e3SSebastian Grimberg       case CEED_RESTRICTION_ORIENTED:
56377d1c127SSebastian Grimberg         scale = 2;
56489edb9e3SSebastian Grimberg         break;
56589edb9e3SSebastian Grimberg       case CEED_RESTRICTION_CURL_ORIENTED:
56677d1c127SSebastian Grimberg         scale = 6;
56789edb9e3SSebastian Grimberg         break;
5686e15d496SJeremy L Thompson     }
56977d1c127SSebastian Grimberg   } else {
57089edb9e3SSebastian Grimberg     switch (rstr_type) {
57189edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STRIDED:
57289edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STANDARD:
5733ac8f562SJeremy L Thompson       case CEED_RESTRICTION_POINTS:
57477d1c127SSebastian Grimberg         scale = 0;
57589edb9e3SSebastian Grimberg         break;
57689edb9e3SSebastian Grimberg       case CEED_RESTRICTION_ORIENTED:
57777d1c127SSebastian Grimberg         scale = 1;
57889edb9e3SSebastian Grimberg         break;
57989edb9e3SSebastian Grimberg       case CEED_RESTRICTION_CURL_ORIENTED:
58077d1c127SSebastian Grimberg         scale = 5;
58189edb9e3SSebastian Grimberg         break;
58277d1c127SSebastian Grimberg     }
58377d1c127SSebastian Grimberg   }
5846e15d496SJeremy L Thompson   *flops = e_size * scale;
5856e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5866e15d496SJeremy L Thompson }
5876e15d496SJeremy L Thompson 
5887a982d89SJeremy L. Thompson /// @}
5897a982d89SJeremy L. Thompson 
59015910d16Sjeremylt /// @cond DOXYGEN_SKIP
59115910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
59215910d16Sjeremylt /// @endcond
59315910d16Sjeremylt 
5947a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5957a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
5967a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5977a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
598d7b241e6Sjeremylt /// @{
599d7b241e6Sjeremylt 
6007a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
60145f1e315Sjeremylt const CeedInt CEED_STRIDES_BACKEND[3] = {0};
6027a982d89SJeremy L. Thompson 
603ca94c3ddSJeremy L Thompson /// Argument for @ref CeedOperatorSetField() indicating that the field does not require a `CeedElemRestriction`
6042b730f8bSJeremy L Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = &ceed_elemrestriction_none;
6057a982d89SJeremy L. Thompson 
606d7b241e6Sjeremylt /**
607ca94c3ddSJeremy L Thompson   @brief Create a `CeedElemRestriction`
608d7b241e6Sjeremylt 
609ca94c3ddSJeremy L Thompson   @param[in]  ceed        `Ceed` context used to create the `CeedElemRestriction`
610ca94c3ddSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the `offsets` array
611ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
612ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
613fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
614ca94c3ddSJeremy 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`.
615fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
616fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
617ca94c3ddSJeremy L Thompson   @param[in]  mem_type    Memory type of the `offsets` array, see @ref CeedMemType
618ca94c3ddSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the `offsets` array, see @ref CeedCopyMode
619ca94c3ddSJeremy L Thompson   @param[in]  offsets     Array of shape `[num_elem, elem_size]`.
620ca94c3ddSJeremy 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.
621ca94c3ddSJeremy L Thompson                             All offsets must be in the range `[0, l_size - 1]`.
622ca94c3ddSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created `CeedElemRestriction` will be stored
623d7b241e6Sjeremylt 
624b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
625dfdf5a53Sjeremylt 
6267a982d89SJeremy L. Thompson   @ref User
627b11c1e72Sjeremylt **/
6282b730f8bSJeremy L Thompson int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
6292b730f8bSJeremy L Thompson                               CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
6305fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
6315fe0d4faSjeremylt     Ceed delegate;
6326574a04fSJeremy L Thompson 
6332b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
634ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreate");
6352b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
636*9bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
637e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6385fe0d4faSjeremylt   }
6395fe0d4faSjeremylt 
640e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
6416574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
642ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
643ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
644e022e1f8SJeremy L Thompson 
6452b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
646db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
647d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
648d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
649d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
650d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
651d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
652d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
6531203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp;
654e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
655e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
65661a27d74SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_STANDARD;
657fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, NULL, *rstr));
658e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
659d7b241e6Sjeremylt }
660d7b241e6Sjeremylt 
661d7b241e6Sjeremylt /**
662ca94c3ddSJeremy L Thompson   @brief Create a `CeedElemRestriction` with orientation signs
663fc0567d9Srezgarshakeri 
664ca94c3ddSJeremy L Thompson   @param[in]  ceed        `Ceed` context used to create the `CeedElemRestriction`
665ca94c3ddSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the `offsets` array
666ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
667ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
668fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
669ca94c3ddSJeremy 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`.
670fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
671fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
672ca94c3ddSJeremy L Thompson   @param[in]  mem_type    Memory type of the `offsets` array, see @ref CeedMemType
673ca94c3ddSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the `offsets` array, see @ref CeedCopyMode
674ca94c3ddSJeremy L Thompson   @param[in]  offsets     Array of shape `[num_elem, elem_size]`.
675ca94c3ddSJeremy 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`.
676ca94c3ddSJeremy L Thompson                             All offsets must be in the range `[0, l_size - 1]`.
677ca94c3ddSJeremy L Thompson   @param[in]  orients     Boolean array of shape `[num_elem, elem_size]` with `false` for positively oriented and `true` to flip the orientation
678ca94c3ddSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created `CeedElemRestriction` will be stored
679fc0567d9Srezgarshakeri 
680fc0567d9Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
681fc0567d9Srezgarshakeri 
682fc0567d9Srezgarshakeri   @ref User
683fc0567d9Srezgarshakeri **/
6842b730f8bSJeremy L Thompson int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
68577d1c127SSebastian Grimberg                                       CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orients,
686fc0567d9Srezgarshakeri                                       CeedElemRestriction *rstr) {
687fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreate) {
688fc0567d9Srezgarshakeri     Ceed delegate;
6896574a04fSJeremy L Thompson 
6902b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
691ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateOriented");
6922b730f8bSJeremy L Thompson     CeedCall(
69377d1c127SSebastian Grimberg         CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, orients, rstr));
694*9bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
695fc0567d9Srezgarshakeri     return CEED_ERROR_SUCCESS;
696fc0567d9Srezgarshakeri   }
697fc0567d9Srezgarshakeri 
698e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
6996574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
700ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
701ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
702e022e1f8SJeremy L Thompson 
7032b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
704db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
705fc0567d9Srezgarshakeri   (*rstr)->ref_count   = 1;
706fc0567d9Srezgarshakeri   (*rstr)->num_elem    = num_elem;
707fc0567d9Srezgarshakeri   (*rstr)->elem_size   = elem_size;
708fc0567d9Srezgarshakeri   (*rstr)->num_comp    = num_comp;
709fc0567d9Srezgarshakeri   (*rstr)->comp_stride = comp_stride;
710fc0567d9Srezgarshakeri   (*rstr)->l_size      = l_size;
7111203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp;
712e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
713e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
714fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_ORIENTED;
715fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, orients, NULL, *rstr));
71677d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
71777d1c127SSebastian Grimberg }
71877d1c127SSebastian Grimberg 
71977d1c127SSebastian Grimberg /**
720ca94c3ddSJeremy L Thompson   @brief Create a `CeedElemRestriction` with a general tridiagonal transformation matrix for curl-conforming elements
72177d1c127SSebastian Grimberg 
722ca94c3ddSJeremy L Thompson   @param[in]  ceed         `Ceed` context used to create the `CeedElemRestriction`
723ca94c3ddSJeremy L Thompson   @param[in]  num_elem     Number of elements described in the `offsets` array
72477d1c127SSebastian Grimberg   @param[in]  elem_size    Size (number of "nodes") per element
72577d1c127SSebastian Grimberg   @param[in]  num_comp     Number of field components per interpolation node (1 for scalar fields)
726fcbe8c06SSebastian Grimberg   @param[in]  comp_stride  Stride between components for the same L-vector "node".
727ca94c3ddSJeremy 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`.
728fcbe8c06SSebastian Grimberg   @param[in]  l_size       The size of the L-vector.
729fcbe8c06SSebastian Grimberg                              This vector may be larger than the elements and fields given by this restriction.
730ca94c3ddSJeremy L Thompson   @param[in]  mem_type     Memory type of the `offsets` array, see @ref CeedMemType
731ca94c3ddSJeremy L Thompson   @param[in]  copy_mode    Copy mode for the `offsets` array, see @ref CeedCopyMode
732ca94c3ddSJeremy L Thompson   @param[in]  offsets      Array of shape `[num_elem, elem_size]`.
733ca94c3ddSJeremy 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`.
734ca94c3ddSJeremy L Thompson                              All offsets must be in the range `[0, l_size - 1]`.
735ca94c3ddSJeremy 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.
736ca94c3ddSJeremy 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).
737ca94c3ddSJeremy L Thompson   @param[out] rstr         Address of the variable where the newly created `CeedElemRestriction` will be stored
73877d1c127SSebastian Grimberg 
73977d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
74077d1c127SSebastian Grimberg 
74177d1c127SSebastian Grimberg   @ref User
74277d1c127SSebastian Grimberg **/
74377d1c127SSebastian Grimberg int CeedElemRestrictionCreateCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
7440c73c039SSebastian Grimberg                                           CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const CeedInt8 *curl_orients,
74577d1c127SSebastian Grimberg                                           CeedElemRestriction *rstr) {
746fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreate) {
74777d1c127SSebastian Grimberg     Ceed delegate;
74877d1c127SSebastian Grimberg 
74977d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
750ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateCurlOriented");
75177d1c127SSebastian Grimberg     CeedCall(CeedElemRestrictionCreateCurlOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
75277d1c127SSebastian Grimberg                                                    curl_orients, rstr));
753*9bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
75477d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
75577d1c127SSebastian Grimberg   }
75677d1c127SSebastian Grimberg 
757e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
75877d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
759ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
760ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
76177d1c127SSebastian Grimberg 
76277d1c127SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
763fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
76477d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
76577d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
76677d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
76777d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
76877d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
76977d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
7701203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp;
771e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
772e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
773fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_CURL_ORIENTED;
774fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, curl_orients, *rstr));
775fc0567d9Srezgarshakeri   return CEED_ERROR_SUCCESS;
776fc0567d9Srezgarshakeri }
777fc0567d9Srezgarshakeri 
778fc0567d9Srezgarshakeri /**
779ca94c3ddSJeremy L Thompson   @brief Create a strided `CeedElemRestriction`
780d7b241e6Sjeremylt 
781ca94c3ddSJeremy L Thompson   @param[in]  ceed      `Ceed` context used to create the `CeedElemRestriction`
782ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
783ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
784ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation "node" (1 for scalar fields)
785fcbe8c06SSebastian Grimberg   @param[in]  l_size    The size of the L-vector.
786fcbe8c06SSebastian Grimberg                           This vector may be larger than the elements and fields given by this restriction.
787ca94c3ddSJeremy L Thompson   @param[in]  strides   Array for strides between `[nodes, components, elements]`.
788ca94c3ddSJeremy 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]`.
789ca94c3ddSJeremy L Thompson                           @ref CEED_STRIDES_BACKEND may be used for `CeedVector` ordered by the same `Ceed` backend.
790972f909dSJeremy L Thompson                           `CEED_STRIDES_BACKEND` should only be used pass data between `CeedOperator` created with the same `Ceed` backend.
791972f909dSJeremy L Thompson                           The L-vector layout will, in general, be different between `Ceed` backends.
792ca94c3ddSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created `CeedElemRestriction` will be stored
793d7b241e6Sjeremylt 
794b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
795dfdf5a53Sjeremylt 
7967a982d89SJeremy L. Thompson   @ref User
797b11c1e72Sjeremylt **/
7982b730f8bSJeremy L Thompson int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedSize l_size, const CeedInt strides[3],
799f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
8005fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
8015fe0d4faSjeremylt     Ceed delegate;
802b04eb3d9SSebastian Grimberg 
8032b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
804ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateStrided");
8052b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, l_size, strides, rstr));
806*9bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
807e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
8085fe0d4faSjeremylt   }
8095fe0d4faSjeremylt 
810e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
8116574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
812ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
813aa72de07SJeremy L Thompson   CeedCheck(l_size >= (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp, ceed, CEED_ERROR_DIMENSION,
814870ea2d9SJeremy L Thompson             "L-vector size must be at least num_elem * elem_size * num_comp. Expected: > %" CeedSize_FMT " Found: %" CeedSize_FMT,
815870ea2d9SJeremy L Thompson             (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp, l_size);
816e022e1f8SJeremy L Thompson 
8172b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
818db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
819d1d35e2fSjeremylt   (*rstr)->ref_count  = 1;
820d1d35e2fSjeremylt   (*rstr)->num_elem   = num_elem;
821d1d35e2fSjeremylt   (*rstr)->elem_size  = elem_size;
822d1d35e2fSjeremylt   (*rstr)->num_comp   = num_comp;
823d1d35e2fSjeremylt   (*rstr)->l_size     = l_size;
8241203703bSJeremy L Thompson   (*rstr)->e_size     = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp;
825e7f679fcSJeremy L Thompson   (*rstr)->num_block  = num_elem;
826e7f679fcSJeremy L Thompson   (*rstr)->block_size = 1;
827fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type  = CEED_RESTRICTION_STRIDED;
8282b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
8292b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
830fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
831e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
832d7b241e6Sjeremylt }
833d7b241e6Sjeremylt 
834d7b241e6Sjeremylt /**
835ca94c3ddSJeremy 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.
8363ac8f562SJeremy L Thompson 
8373ac8f562SJeremy L Thompson   The offsets array is arranged as
8383ac8f562SJeremy L Thompson 
8393ac8f562SJeremy L Thompson   element_0_start_index
8403ac8f562SJeremy L Thompson   element_1_start_index
8413ac8f562SJeremy L Thompson   ...
8423ac8f562SJeremy L Thompson   element_n_start_index
8433ac8f562SJeremy L Thompson   element_n_stop_index
8443ac8f562SJeremy L Thompson   element_0_point_0
8453ac8f562SJeremy L Thompson   element_0_point_1
8463ac8f562SJeremy L Thompson   ...
8473ac8f562SJeremy L Thompson 
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
850ca94c3ddSJeremy L Thompson   @param[in]  num_points Number of points described in the `offsets` array
8513ac8f562SJeremy L Thompson   @param[in]  num_comp   Number of field components per interpolation node (1 for scalar fields).
8523ac8f562SJeremy L Thompson                            Components are assumed to be contiguous by point.
8533ac8f562SJeremy L Thompson   @param[in]  l_size     The size of the L-vector.
8543ac8f562SJeremy L Thompson                            This vector may be larger than the elements and fields given by this restriction.
855ca94c3ddSJeremy L Thompson   @param[in]  mem_type   Memory type of the `offsets` array, see @ref CeedMemType
856ca94c3ddSJeremy L Thompson   @param[in]  copy_mode  Copy mode for the `offsets` array, see @ref CeedCopyMode
857ca94c3ddSJeremy L Thompson   @param[in]  offsets    Array of size `num_elem + 1 + num_points`.
8583ac8f562SJeremy L Thompson                            The first portion of the offsets array holds the ranges of indices corresponding to each element.
8593ac8f562SJeremy L Thompson                            The second portion holds the indices for each element.
860ca94c3ddSJeremy L Thompson   @param[out] rstr       Address of the variable where the newly created `CeedElemRestriction` will be stored
8613ac8f562SJeremy L Thompson 
8623ac8f562SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
8633ac8f562SJeremy L Thompson 
8643ac8f562SJeremy L Thompson   @ref Backend
8653ac8f562SJeremy L Thompson  **/
8663ac8f562SJeremy L Thompson int CeedElemRestrictionCreateAtPoints(Ceed ceed, CeedInt num_elem, CeedInt num_points, CeedInt num_comp, CeedSize l_size, CeedMemType mem_type,
8673ac8f562SJeremy L Thompson                                       CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
8683ac8f562SJeremy L Thompson   if (!ceed->ElemRestrictionCreateAtPoints) {
8693ac8f562SJeremy L Thompson     Ceed delegate;
8703ac8f562SJeremy L Thompson 
8713ac8f562SJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
872ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateAtPoints");
8733ac8f562SJeremy L Thompson     CeedCall(CeedElemRestrictionCreateAtPoints(delegate, num_elem, num_points, num_comp, l_size, mem_type, copy_mode, offsets, rstr));
874*9bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
8753ac8f562SJeremy L Thompson     return CEED_ERROR_SUCCESS;
8763ac8f562SJeremy L Thompson   }
8773ac8f562SJeremy L Thompson 
8783ac8f562SJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
8793ac8f562SJeremy L Thompson   CeedCheck(num_points >= 0, ceed, CEED_ERROR_DIMENSION, "Number of points must be non-negative");
880ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
881870ea2d9SJeremy L Thompson   CeedCheck(l_size >= (CeedSize)num_points * num_comp, ceed, CEED_ERROR_DIMENSION,
882870ea2d9SJeremy L Thompson             "L-vector must be at least num_points * num_comp. Expected: > %" CeedSize_FMT " Found: %" CeedSize_FMT, (CeedSize)num_points * num_comp,
883870ea2d9SJeremy L Thompson             l_size);
8843ac8f562SJeremy L Thompson 
8853ac8f562SJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
8863ac8f562SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
8873ac8f562SJeremy L Thompson   (*rstr)->ref_count   = 1;
8883ac8f562SJeremy L Thompson   (*rstr)->num_elem    = num_elem;
8893ac8f562SJeremy L Thompson   (*rstr)->num_points  = num_points;
8903ac8f562SJeremy L Thompson   (*rstr)->num_comp    = num_comp;
8912c2c926cSJeremy L Thompson   (*rstr)->comp_stride = 1;
8923ac8f562SJeremy L Thompson   (*rstr)->l_size      = l_size;
8931203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_points * (CeedSize)num_comp;
89405fa913cSJeremy L Thompson   (*rstr)->num_block   = num_elem;
8953ac8f562SJeremy L Thompson   (*rstr)->block_size  = 1;
8963ac8f562SJeremy L Thompson   (*rstr)->rstr_type   = CEED_RESTRICTION_POINTS;
8973ac8f562SJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateAtPoints(mem_type, copy_mode, offsets, NULL, NULL, *rstr));
8983ac8f562SJeremy L Thompson   return CEED_ERROR_SUCCESS;
8993ac8f562SJeremy L Thompson }
9003ac8f562SJeremy L Thompson 
9013ac8f562SJeremy L Thompson /**
902ca94c3ddSJeremy L Thompson   @brief Create a blocked `CeedElemRestriction`, typically only used by backends
903d7b241e6Sjeremylt 
904ca94c3ddSJeremy L Thompson   @param[in]  ceed        `Ceed` context used to create the `CeedElemRestriction`
905ca94c3ddSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the `offsets` array
906ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of unknowns) per element
907e7f679fcSJeremy L Thompson   @param[in]  block_size  Number of elements in a block
908ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
909fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
910ca94c3ddSJeremy 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`.
911fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
912fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
913ca94c3ddSJeremy L Thompson   @param[in]  mem_type    Memory type of the `offsets` array, see @ref CeedMemType
914ca94c3ddSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the `offsets` array, see @ref CeedCopyMode
915ca94c3ddSJeremy L Thompson   @param[in]  offsets     Array of shape `[num_elem, elem_size]`.
916ca94c3ddSJeremy 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`.
917ca94c3ddSJeremy L Thompson                             All offsets must be in the range `[0, l_size - 1]`.
918ca94c3ddSJeremy L Thompson                             The backend will permute and pad this array to the desired ordering for the blocksize, which is typically given by the backend.
919ca94c3ddSJeremy L Thompson                             The default reordering is to interlace elements.
920ca94c3ddSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created `CeedElemRestriction` will be stored
921d7b241e6Sjeremylt 
922b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
923dfdf5a53Sjeremylt 
9247a982d89SJeremy L. Thompson   @ref Backend
925b11c1e72Sjeremylt  **/
926e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedInt comp_stride,
9272b730f8bSJeremy L Thompson                                      CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets,
9284ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
9291c66c397SJeremy L Thompson   CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
930d7b241e6Sjeremylt 
9315fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
9325fe0d4faSjeremylt     Ceed delegate;
9336574a04fSJeremy L Thompson 
9342b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
935ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlocked");
936e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
937e7f679fcSJeremy L Thompson                                               rstr));
938*9bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
939e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
9405fe0d4faSjeremylt   }
941d7b241e6Sjeremylt 
942e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
9436574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
944e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
945ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
946ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
947e022e1f8SJeremy L Thompson 
948e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
949e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
950d7b241e6Sjeremylt 
951db002c03SJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
952db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
953d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
954d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
955d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
956d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
957d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
958d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
9591203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
960e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
961e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
96261a27d74SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_STANDARD;
963e7f679fcSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL, NULL, *rstr));
9641c66c397SJeremy L Thompson   if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
965e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
966d7b241e6Sjeremylt }
967d7b241e6Sjeremylt 
968b11c1e72Sjeremylt /**
969ca94c3ddSJeremy L Thompson   @brief Create a blocked oriented `CeedElemRestriction`, typically only used by backends
97077d1c127SSebastian Grimberg 
971ca94c3ddSJeremy L Thompson   @param[in]  ceed        `Ceed` context used to create the `CeedElemRestriction`
972ca94c3ddSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the `offsets` array.
97377d1c127SSebastian Grimberg   @param[in]  elem_size   Size (number of unknowns) per element
974e7f679fcSJeremy L Thompson   @param[in]  block_size  Number of elements in a block
97577d1c127SSebastian Grimberg   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
976fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
977ca94c3ddSJeremy 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`.
978fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
979fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
980ca94c3ddSJeremy L Thompson   @param[in]  mem_type    Memory type of the `offsets` array, see @ref CeedMemType
981ca94c3ddSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the `offsets` array, see @ref CeedCopyMode
982ca94c3ddSJeremy L Thompson   @param[in]  offsets     Array of shape `[num_elem, elem_size]`.
983ca94c3ddSJeremy 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`.
984ca94c3ddSJeremy L Thompson                             All offsets must be in the range `[0, l_size - 1]`.
985ca94c3ddSJeremy L Thompson                             The backend will permute and pad this array to the desired ordering for the blocksize, which is typically given by the backend.
986ca94c3ddSJeremy L Thompson                             The default reordering is to interlace elements.
987ca94c3ddSJeremy L Thompson   @param[in]  orients     Boolean array of shape `[num_elem, elem_size]` with `false` for positively oriented and `true` to flip the orientation.
988ca94c3ddSJeremy L Thompson                             Will also be permuted and padded similarly to `offsets`.
989ca94c3ddSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created `CeedElemRestriction` will be stored
99077d1c127SSebastian Grimberg 
99177d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
99277d1c127SSebastian Grimberg 
99377d1c127SSebastian Grimberg   @ref Backend
99477d1c127SSebastian Grimberg  **/
995e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp,
996e7f679fcSJeremy L Thompson                                              CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode,
997e7f679fcSJeremy L Thompson                                              const CeedInt *offsets, const bool *orients, CeedElemRestriction *rstr) {
998e7f679fcSJeremy L Thompson   bool    *block_orients;
9991c66c397SJeremy L Thompson   CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
100077d1c127SSebastian Grimberg 
1001fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreateBlocked) {
100277d1c127SSebastian Grimberg     Ceed delegate;
100377d1c127SSebastian Grimberg 
100477d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
1005ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedOriented");
1006e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode,
100777d1c127SSebastian Grimberg                                                       offsets, orients, rstr));
1008*9bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
100977d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
101077d1c127SSebastian Grimberg   }
101177d1c127SSebastian Grimberg 
101277d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
1013e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
1014ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
1015ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
101677d1c127SSebastian Grimberg 
1017e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
1018e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_orients));
1019e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
1020e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOrients(orients, block_orients, num_block, num_elem, block_size, elem_size));
102177d1c127SSebastian Grimberg 
1022fcbe8c06SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
1023fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
102477d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
102577d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
102677d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
102777d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
102877d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
102977d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
10301203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1031e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
1032e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
1033fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_ORIENTED;
1034e7f679fcSJeremy L Thompson   CeedCall(
1035e7f679fcSJeremy L Thompson       ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, (const bool *)block_orients, NULL, *rstr));
10361c66c397SJeremy L Thompson   if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
103777d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
103877d1c127SSebastian Grimberg }
103977d1c127SSebastian Grimberg 
104077d1c127SSebastian Grimberg /**
1041ca94c3ddSJeremy L Thompson   @brief Create a blocked curl-oriented `CeedElemRestriction`, typically only used by backends
104277d1c127SSebastian Grimberg 
1043ca94c3ddSJeremy L Thompson   @param[in]  ceed         `Ceed` context used to create the `CeedElemRestriction`
1044ca94c3ddSJeremy L Thompson   @param[in]  num_elem     Number of elements described in the `offsets` array.
104577d1c127SSebastian Grimberg   @param[in]  elem_size    Size (number of unknowns) per element
1046e7f679fcSJeremy L Thompson   @param[in]  block_size   Number of elements in a block
104777d1c127SSebastian Grimberg   @param[in]  num_comp     Number of field components per interpolation node (1 for scalar fields)
1048fcbe8c06SSebastian Grimberg   @param[in]  comp_stride  Stride between components for the same L-vector "node".
1049ca94c3ddSJeremy 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`.
1050fcbe8c06SSebastian Grimberg   @param[in]  l_size       The size of the L-vector.
1051fcbe8c06SSebastian Grimberg                              This vector may be larger than the elements and fields given by this restriction.
1052ca94c3ddSJeremy L Thompson   @param[in]  mem_type     Memory type of the `offsets` array, see @ref CeedMemType
1053ca94c3ddSJeremy L Thompson   @param[in]  copy_mode    Copy mode for the `offsets` array, see @ref CeedCopyMode
1054ca94c3ddSJeremy L Thompson   @param[in]  offsets      Array of shape `[num_elem, elem_size]`.
1055ca94c3ddSJeremy 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`.
1056ca94c3ddSJeremy L Thompson                              All offsets must be in the range `[0, l_size - 1]`.
1057ca94c3ddSJeremy L Thompson                              The backend will permute and pad this array to the desired  ordering for the blocksize, which is typically given by the backend.
1058ca94c3ddSJeremy L Thompson                              The default reordering is to interlace elements.
1059ca94c3ddSJeremy 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.
1060ca94c3ddSJeremy 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).
1061ca94c3ddSJeremy L Thompson                              Will also be permuted and padded similarly to offsets.
1062ca94c3ddSJeremy L Thompson   @param[out] rstr         Address of the variable where the newly created `CeedElemRestriction` will be stored
106377d1c127SSebastian Grimberg 
106477d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
106577d1c127SSebastian Grimberg 
106677d1c127SSebastian Grimberg   @ref Backend
106777d1c127SSebastian Grimberg  **/
1068e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp,
106977d1c127SSebastian Grimberg                                                  CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode,
10700c73c039SSebastian Grimberg                                                  const CeedInt *offsets, const CeedInt8 *curl_orients, CeedElemRestriction *rstr) {
1071e7f679fcSJeremy L Thompson   CeedInt8 *block_curl_orients;
10721c66c397SJeremy L Thompson   CeedInt  *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
107377d1c127SSebastian Grimberg 
1074fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreateBlocked) {
107577d1c127SSebastian Grimberg     Ceed delegate;
107677d1c127SSebastian Grimberg 
107777d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
1078ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedCurlOriented");
1079e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedCurlOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type,
1080e7f679fcSJeremy L Thompson                                                           copy_mode, offsets, curl_orients, rstr));
1081*9bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
108277d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
108377d1c127SSebastian Grimberg   }
108477d1c127SSebastian Grimberg 
1085e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
108677d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
1087e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
1088ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
1089ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
109077d1c127SSebastian Grimberg 
1091e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
1092e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * 3 * elem_size, &block_curl_orients));
1093e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
1094e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadCurlOrients(curl_orients, block_curl_orients, num_block, num_elem, block_size, 3 * elem_size));
109577d1c127SSebastian Grimberg 
1096fcbe8c06SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
1097fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
109877d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
109977d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
110077d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
110177d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
110277d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
110377d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
11041203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1105e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
1106e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
1107fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_CURL_ORIENTED;
1108e7f679fcSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL,
1109e7f679fcSJeremy L Thompson                                               (const CeedInt8 *)block_curl_orients, *rstr));
11101c66c397SJeremy L Thompson   if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
111177d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
111277d1c127SSebastian Grimberg }
111377d1c127SSebastian Grimberg 
111477d1c127SSebastian Grimberg /**
1115ca94c3ddSJeremy L Thompson   @brief Create a blocked strided `CeedElemRestriction`, typically only used by backends
11167509a596Sjeremylt 
1117ca94c3ddSJeremy L Thompson   @param[in]  ceed        `Ceed` context used to create the `CeedElemRestriction`
1118ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described by the restriction
1119ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
1120e7f679fcSJeremy L Thompson   @param[in]  block_size  Number of elements in a block
1121ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
1122fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
1123fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
1124ca94c3ddSJeremy L Thompson   @param[in]  strides     Array for strides between `[nodes, components, elements]`.
1125ca94c3ddSJeremy 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]`.
1126ca94c3ddSJeremy L Thompson                             @ref CEED_STRIDES_BACKEND may be used for `CeedVector` ordered by the same `Ceed` backend.
1127ca94c3ddSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created `CeedElemRestriction` will be stored
11287509a596Sjeremylt 
11297509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
11307509a596Sjeremylt 
11317a982d89SJeremy L. Thompson   @ref User
11327509a596Sjeremylt **/
1133e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedSize l_size,
11348621c6c6SJeremy L Thompson                                             const CeedInt strides[3], CeedElemRestriction *rstr) {
1135e7f679fcSJeremy L Thompson   CeedInt num_block = (num_elem / block_size) + !!(num_elem % block_size);
11367509a596Sjeremylt 
11377509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
11387509a596Sjeremylt     Ceed delegate;
11396574a04fSJeremy L Thompson 
11402b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
1141ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedStrided");
1142e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, block_size, num_comp, l_size, strides, rstr));
1143*9bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
1144e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
11457509a596Sjeremylt   }
11467509a596Sjeremylt 
1147e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
11486574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
1149e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
1150ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
1151aa72de07SJeremy L Thompson   CeedCheck(l_size >= (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp, ceed, CEED_ERROR_DIMENSION,
1152870ea2d9SJeremy L Thompson             "L-vector size must be at least num_elem * elem_size * num_comp. Expected: > %" CeedSize_FMT " Found: %" CeedSize_FMT,
1153870ea2d9SJeremy L Thompson             (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp, l_size);
1154e022e1f8SJeremy L Thompson 
11552b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
1156db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
1157d1d35e2fSjeremylt   (*rstr)->ref_count  = 1;
1158d1d35e2fSjeremylt   (*rstr)->num_elem   = num_elem;
1159d1d35e2fSjeremylt   (*rstr)->elem_size  = elem_size;
1160d1d35e2fSjeremylt   (*rstr)->num_comp   = num_comp;
1161d1d35e2fSjeremylt   (*rstr)->l_size     = l_size;
11621203703bSJeremy L Thompson   (*rstr)->e_size     = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1163e7f679fcSJeremy L Thompson   (*rstr)->num_block  = num_block;
1164e7f679fcSJeremy L Thompson   (*rstr)->block_size = block_size;
1165fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type  = CEED_RESTRICTION_STRIDED;
11662b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
11672b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
1168fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
1169e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
11707509a596Sjeremylt }
11717509a596Sjeremylt 
11727509a596Sjeremylt /**
1173ca94c3ddSJeremy L Thompson   @brief Copy the pointer to a `CeedElemRestriction` and set @ref CeedElemRestrictionApply() implementation to use the unsigned version.
1174c17ec2beSJeremy L Thompson 
1175ca94c3ddSJeremy L Thompson   Both pointers should be destroyed with @ref CeedElemRestrictionDestroy().
1176c17ec2beSJeremy L Thompson 
1177ca94c3ddSJeremy L Thompson   @param[in]     rstr          `CeedElemRestriction` to create unsigned reference to
1178ca94c3ddSJeremy L Thompson   @param[in,out] rstr_unsigned Variable to store unsigned `CeedElemRestriction`
1179c17ec2beSJeremy L Thompson 
1180c17ec2beSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1181c17ec2beSJeremy L Thompson 
1182c17ec2beSJeremy L Thompson   @ref User
1183c17ec2beSJeremy L Thompson **/
1184c17ec2beSJeremy L Thompson int CeedElemRestrictionCreateUnsignedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unsigned) {
1185c17ec2beSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr_unsigned));
1186c17ec2beSJeremy L Thompson 
1187c17ec2beSJeremy L Thompson   // Copy old rstr
1188c17ec2beSJeremy L Thompson   memcpy(*rstr_unsigned, rstr, sizeof(struct CeedElemRestriction_private));
1189c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ceed = NULL;
1190c17ec2beSJeremy L Thompson   CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unsigned)->ceed));
1191c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ref_count = 1;
1192c17ec2beSJeremy L Thompson   (*rstr_unsigned)->strides   = NULL;
1193c17ec2beSJeremy L Thompson   if (rstr->strides) {
1194c17ec2beSJeremy L Thompson     CeedCall(CeedMalloc(3, &(*rstr_unsigned)->strides));
1195c17ec2beSJeremy L Thompson     for (CeedInt i = 0; i < 3; i++) (*rstr_unsigned)->strides[i] = rstr->strides[i];
1196c17ec2beSJeremy L Thompson   }
11977c1dbaffSSebastian Grimberg   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unsigned)->rstr_base));
1198c17ec2beSJeremy L Thompson 
1199c17ec2beSJeremy L Thompson   // Override Apply
1200c17ec2beSJeremy L Thompson   (*rstr_unsigned)->Apply = rstr->ApplyUnsigned;
1201c17ec2beSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1202c17ec2beSJeremy L Thompson }
1203c17ec2beSJeremy L Thompson 
1204c17ec2beSJeremy L Thompson /**
1205ca94c3ddSJeremy L Thompson   @brief Copy the pointer to a `CeedElemRestriction` and set @ref CeedElemRestrictionApply() implementation to use the unoriented version.
12067c1dbaffSSebastian Grimberg 
1207ca94c3ddSJeremy L Thompson   Both pointers should be destroyed with @ref CeedElemRestrictionDestroy().
12087c1dbaffSSebastian Grimberg 
1209ca94c3ddSJeremy L Thompson   @param[in]     rstr            `CeedElemRestriction` to create unoriented reference to
1210ca94c3ddSJeremy L Thompson   @param[in,out] rstr_unoriented Variable to store unoriented `CeedElemRestriction`
12117c1dbaffSSebastian Grimberg 
12127c1dbaffSSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
12137c1dbaffSSebastian Grimberg 
12147c1dbaffSSebastian Grimberg   @ref User
12157c1dbaffSSebastian Grimberg **/
12167c1dbaffSSebastian Grimberg int CeedElemRestrictionCreateUnorientedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unoriented) {
12177c1dbaffSSebastian Grimberg   CeedCall(CeedCalloc(1, rstr_unoriented));
12187c1dbaffSSebastian Grimberg 
12197c1dbaffSSebastian Grimberg   // Copy old rstr
12207c1dbaffSSebastian Grimberg   memcpy(*rstr_unoriented, rstr, sizeof(struct CeedElemRestriction_private));
12217c1dbaffSSebastian Grimberg   (*rstr_unoriented)->ceed = NULL;
12227c1dbaffSSebastian Grimberg   CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unoriented)->ceed));
12237c1dbaffSSebastian Grimberg   (*rstr_unoriented)->ref_count = 1;
12247c1dbaffSSebastian Grimberg   (*rstr_unoriented)->strides   = NULL;
12257c1dbaffSSebastian Grimberg   if (rstr->strides) {
12267c1dbaffSSebastian Grimberg     CeedCall(CeedMalloc(3, &(*rstr_unoriented)->strides));
12277c1dbaffSSebastian Grimberg     for (CeedInt i = 0; i < 3; i++) (*rstr_unoriented)->strides[i] = rstr->strides[i];
12287c1dbaffSSebastian Grimberg   }
12297c1dbaffSSebastian Grimberg   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unoriented)->rstr_base));
12307c1dbaffSSebastian Grimberg 
12317c1dbaffSSebastian Grimberg   // Override Apply
12327c1dbaffSSebastian Grimberg   (*rstr_unoriented)->Apply = rstr->ApplyUnoriented;
12337c1dbaffSSebastian Grimberg   return CEED_ERROR_SUCCESS;
12347c1dbaffSSebastian Grimberg }
12357c1dbaffSSebastian Grimberg 
12367c1dbaffSSebastian Grimberg /**
1237ca94c3ddSJeremy L Thompson   @brief Copy the pointer to a `CeedElemRestriction`.
12389fd66db6SSebastian Grimberg 
1239ca94c3ddSJeremy L Thompson   Both pointers should be destroyed with @ref CeedElemRestrictionDestroy().
12409560d06aSjeremylt 
1241ca94c3ddSJeremy 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`.
1242ca94c3ddSJeremy L Thompson         This `CeedElemRestriction` will be destroyed if `*rstr_copy` is the only reference to this `CeedElemRestriction`.
1243ea61e9acSJeremy L Thompson 
1244ca94c3ddSJeremy L Thompson   @param[in]     rstr      `CeedElemRestriction` to copy reference to
1245ea61e9acSJeremy L Thompson   @param[in,out] rstr_copy Variable to store copied reference
12469560d06aSjeremylt 
12479560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
12489560d06aSjeremylt 
12499560d06aSjeremylt   @ref User
12509560d06aSjeremylt **/
12512b730f8bSJeremy L Thompson int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_copy) {
1252393ac2cdSJeremy L Thompson   if (rstr != CEED_ELEMRESTRICTION_NONE) CeedCall(CeedElemRestrictionReference(rstr));
12532b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionDestroy(rstr_copy));
12549560d06aSjeremylt   *rstr_copy = rstr;
12559560d06aSjeremylt   return CEED_ERROR_SUCCESS;
12569560d06aSjeremylt }
12579560d06aSjeremylt 
12589560d06aSjeremylt /**
1259ca94c3ddSJeremy L Thompson   @brief Create `CeedVector` associated with a `CeedElemRestriction`
1260b11c1e72Sjeremylt 
1261ca94c3ddSJeremy L Thompson   @param[in]  rstr  `CeedElemRestriction`
1262ca94c3ddSJeremy L Thompson   @param[out] l_vec The address of the L-vector to be created, or `NULL`
1263ca94c3ddSJeremy L Thompson   @param[out] e_vec The address of the E-vector to be created, or `NULL`
1264b11c1e72Sjeremylt 
1265b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1266dfdf5a53Sjeremylt 
12677a982d89SJeremy L. Thompson   @ref User
1268b11c1e72Sjeremylt **/
12692b730f8bSJeremy L Thompson int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, CeedVector *e_vec) {
1270d2643443SJeremy L Thompson   CeedSize e_size, l_size;
12711203703bSJeremy L Thompson   Ceed     ceed;
127248acf710SJeremy L Thompson 
12731203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
12741203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &l_size));
12751203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &e_size));
12761203703bSJeremy L Thompson   if (l_vec) CeedCall(CeedVectorCreate(ceed, l_size, l_vec));
12771203703bSJeremy L Thompson   if (e_vec) CeedCall(CeedVectorCreate(ceed, e_size, e_vec));
1278*9bc66399SJeremy L Thompson   CeedCall(CeedDestroy(&ceed));
1279e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1280d7b241e6Sjeremylt }
1281d7b241e6Sjeremylt 
1282d7b241e6Sjeremylt /**
1283d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
1284d7b241e6Sjeremylt 
1285ca94c3ddSJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
1286ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1287ca94c3ddSJeremy L Thompson   @param[in]  u       Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE)
1288ca94c3ddSJeremy L Thompson   @param[out] ru      Output vector (of shape `[num_elem * elem_size]` when `t_mode` = @ref CEED_NOTRANSPOSE).
1289fcbe8c06SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
1290ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
1291b11c1e72Sjeremylt 
1292b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1293dfdf5a53Sjeremylt 
12947a982d89SJeremy L. Thompson   @ref User
1295b11c1e72Sjeremylt **/
12962b730f8bSJeremy L Thompson int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
1297701e7d35SJeremy L Thompson   CeedSize min_u_len, min_ru_len, len;
1298701e7d35SJeremy L Thompson   CeedInt  num_elem;
1299d7b241e6Sjeremylt 
1300d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
1301701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &min_ru_len));
1302701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_u_len));
1303d7b241e6Sjeremylt   } else {
1304701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &min_u_len));
1305701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_ru_len));
1306d7b241e6Sjeremylt   }
1307701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(u, &len));
1308*9bc66399SJeremy L Thompson   CeedCheck(min_u_len <= len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
1309701e7d35SJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_ru_len,
1310701e7d35SJeremy L Thompson             min_u_len);
1311701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(ru, &len));
1312*9bc66399SJeremy L Thompson   CeedCheck(min_ru_len <= len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
1313701e7d35SJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_u_len,
1314701e7d35SJeremy L Thompson             min_ru_len);
1315701e7d35SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
1316701e7d35SJeremy L Thompson   if (num_elem > 0) CeedCall(rstr->Apply(rstr, t_mode, u, ru, request));
1317e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1318d7b241e6Sjeremylt }
1319d7b241e6Sjeremylt 
1320d7b241e6Sjeremylt /**
13213ac8f562SJeremy L Thompson   @brief Restrict an L-vector of points to a single element or apply its transpose
13223ac8f562SJeremy L Thompson 
1323ca94c3ddSJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
1324ca94c3ddSJeremy L Thompson   @param[in]  elem    Element number in range `[0, num_elem)`
13253ac8f562SJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1326ca94c3ddSJeremy L Thompson   @param[in]  u       Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE)
1327ca94c3ddSJeremy L Thompson   @param[out] ru      Output vector (of shape [`num_points * num_comp]` when `t_mode` = @ref CEED_NOTRANSPOSE).
13283ac8f562SJeremy L Thompson                         Ordering of the e-vector is decided by the backend.
13293ac8f562SJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
13303ac8f562SJeremy L Thompson 
13313ac8f562SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
13323ac8f562SJeremy L Thompson 
13333ac8f562SJeremy L Thompson   @ref User
13343ac8f562SJeremy L Thompson **/
133505fa913cSJeremy L Thompson int CeedElemRestrictionApplyAtPointsInElement(CeedElemRestriction rstr, CeedInt elem, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
13363ac8f562SJeremy L Thompson                                               CeedRequest *request) {
1337701e7d35SJeremy L Thompson   CeedSize min_u_len, min_ru_len, len;
1338701e7d35SJeremy L Thompson   CeedInt  num_elem;
13393ac8f562SJeremy L Thompson 
1340*9bc66399SJeremy L Thompson   CeedCheck(rstr->ApplyAtPointsInElement, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED,
1341*9bc66399SJeremy L Thompson             "Backend does not implement CeedElemRestrictionApplyAtPointsInElement");
13421ef3a2a9SJeremy L Thompson 
13433ac8f562SJeremy L Thompson   if (t_mode == CEED_NOTRANSPOSE) {
1344701e7d35SJeremy L Thompson     CeedInt num_points, num_comp;
1345701e7d35SJeremy L Thompson 
1346701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_u_len));
1347701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, elem, &num_points));
1348701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
1349701e7d35SJeremy L Thompson     min_ru_len = (CeedSize)num_points * (CeedSize)num_comp;
13503ac8f562SJeremy L Thompson   } else {
1351701e7d35SJeremy L Thompson     CeedInt num_points, num_comp;
1352701e7d35SJeremy L Thompson 
1353701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, elem, &num_points));
1354701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
1355701e7d35SJeremy L Thompson     min_u_len = (CeedSize)num_points * (CeedSize)num_comp;
1356701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_ru_len));
13573ac8f562SJeremy L Thompson   }
1358701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(u, &len));
1359*9bc66399SJeremy L Thompson   CeedCheck(min_u_len <= len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
13603ac8f562SJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT
13613ac8f562SJeremy L Thompson             ") for element %" CeedInt_FMT,
1362701e7d35SJeremy L Thompson             len, min_ru_len, min_u_len, elem);
1363701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(ru, &len));
1364*9bc66399SJeremy L Thompson   CeedCheck(min_ru_len <= len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
13653ac8f562SJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT
13663ac8f562SJeremy L Thompson             ") for element %" CeedInt_FMT,
1367701e7d35SJeremy L Thompson             len, min_ru_len, min_u_len, elem);
1368701e7d35SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
1369*9bc66399SJeremy L Thompson   CeedCheck(elem < num_elem, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
1370701e7d35SJeremy L Thompson             "Cannot retrieve element %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", elem, elem, num_elem);
1371701e7d35SJeremy L Thompson   if (num_elem > 0) CeedCall(rstr->ApplyAtPointsInElement(rstr, elem, t_mode, u, ru, request));
13723ac8f562SJeremy L Thompson   return CEED_ERROR_SUCCESS;
13733ac8f562SJeremy L Thompson }
13743ac8f562SJeremy L Thompson 
13753ac8f562SJeremy L Thompson /**
1376d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
1377be9261b7Sjeremylt 
1378ca94c3ddSJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
1379ca94c3ddSJeremy 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]`
1380ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1381ca94c3ddSJeremy L Thompson   @param[in]  u       Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE)
1382ca94c3ddSJeremy L Thompson   @param[out] ru      Output vector (of shape `[block_size * elem_size]` when `t_mode` = @ref CEED_NOTRANSPOSE).
1383fcbe8c06SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
1384ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
1385be9261b7Sjeremylt 
1386be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
1387be9261b7Sjeremylt 
13887a982d89SJeremy L. Thompson   @ref Backend
1389be9261b7Sjeremylt **/
13902b730f8bSJeremy L Thompson int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
13912b730f8bSJeremy L Thompson                                   CeedRequest *request) {
1392701e7d35SJeremy L Thompson   CeedSize min_u_len, min_ru_len, len;
1393701e7d35SJeremy L Thompson   CeedInt  block_size, num_elem;
1394be9261b7Sjeremylt 
1395*9bc66399SJeremy L Thompson   CeedCheck(rstr->ApplyBlock, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED,
1396*9bc66399SJeremy L Thompson             "Backend does not implement CeedElemRestrictionApplyBlock");
13976402da51SJeremy L Thompson 
1398701e7d35SJeremy L Thompson   CeedCall(CeedElemRestrictionGetBlockSize(rstr, &block_size));
1399d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
1400701e7d35SJeremy L Thompson     CeedInt elem_size, num_comp;
1401701e7d35SJeremy L Thompson 
1402701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetElementSize(rstr, &elem_size));
1403701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
1404701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_u_len));
1405701e7d35SJeremy L Thompson     min_ru_len = (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1406be9261b7Sjeremylt   } else {
1407701e7d35SJeremy L Thompson     CeedInt elem_size, num_comp;
1408701e7d35SJeremy L Thompson 
1409701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetElementSize(rstr, &elem_size));
1410701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
1411701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_ru_len));
1412701e7d35SJeremy L Thompson     min_u_len = (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1413be9261b7Sjeremylt   }
1414701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(u, &len));
1415*9bc66399SJeremy L Thompson   CeedCheck(min_u_len == len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
1416701e7d35SJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_u_len,
1417701e7d35SJeremy L Thompson             min_ru_len);
1418701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(ru, &len));
1419*9bc66399SJeremy L Thompson   CeedCheck(min_ru_len == len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
1420701e7d35SJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_ru_len,
1421701e7d35SJeremy L Thompson             min_u_len);
1422701e7d35SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
1423*9bc66399SJeremy L Thompson   CeedCheck(block_size * block <= num_elem, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
1424701e7d35SJeremy L Thompson             "Cannot retrieve block %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", block, block_size * block,
1425701e7d35SJeremy L Thompson             num_elem);
14262b730f8bSJeremy L Thompson   CeedCall(rstr->ApplyBlock(rstr, block, t_mode, u, ru, request));
1427e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1428be9261b7Sjeremylt }
1429be9261b7Sjeremylt 
1430be9261b7Sjeremylt /**
1431ca94c3ddSJeremy L Thompson   @brief Get the `Ceed` associated with a `CeedElemRestriction`
1432b7c9bbdaSJeremy L Thompson 
1433ca94c3ddSJeremy L Thompson   @param[in]  rstr `CeedElemRestriction`
1434ca94c3ddSJeremy L Thompson   @param[out] ceed Variable to store `Ceed`
1435b7c9bbdaSJeremy L Thompson 
1436b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1437b7c9bbdaSJeremy L Thompson 
1438b7c9bbdaSJeremy L Thompson   @ref Advanced
1439b7c9bbdaSJeremy L Thompson **/
1440b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
1441*9bc66399SJeremy L Thompson   *ceed = NULL;
1442*9bc66399SJeremy L Thompson   CeedCall(CeedReferenceCopy(CeedElemRestrictionReturnCeed(rstr), ceed));
1443b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1444b7c9bbdaSJeremy L Thompson }
1445b7c9bbdaSJeremy L Thompson 
1446b7c9bbdaSJeremy L Thompson /**
14476e536b99SJeremy L Thompson   @brief Return the `Ceed` associated with a `CeedElemRestriction`
14486e536b99SJeremy L Thompson 
14496e536b99SJeremy L Thompson   @param[in]  rstr `CeedElemRestriction`
14506e536b99SJeremy L Thompson 
14516e536b99SJeremy L Thompson   @return `Ceed` associated with the `rstr`
14526e536b99SJeremy L Thompson 
14536e536b99SJeremy L Thompson   @ref Advanced
14546e536b99SJeremy L Thompson **/
14556e536b99SJeremy L Thompson Ceed CeedElemRestrictionReturnCeed(CeedElemRestriction rstr) { return rstr->ceed; }
14566e536b99SJeremy L Thompson 
14576e536b99SJeremy L Thompson /**
1458d979a051Sjeremylt   @brief Get the L-vector component stride
1459a681ae63Sjeremylt 
1460ca94c3ddSJeremy L Thompson   @param[in]  rstr        `CeedElemRestriction`
1461d1d35e2fSjeremylt   @param[out] comp_stride Variable to store component stride
1462a681ae63Sjeremylt 
1463a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1464a681ae63Sjeremylt 
1465b7c9bbdaSJeremy L Thompson   @ref Advanced
1466a681ae63Sjeremylt **/
14672b730f8bSJeremy L Thompson int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, CeedInt *comp_stride) {
1468d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
1469e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1470a681ae63Sjeremylt }
1471a681ae63Sjeremylt 
1472a681ae63Sjeremylt /**
1473ca94c3ddSJeremy L Thompson   @brief Get the total number of elements in the range of a `CeedElemRestriction`
1474a681ae63Sjeremylt 
1475ca94c3ddSJeremy L Thompson   @param[in] rstr      `CeedElemRestriction`
1476d1d35e2fSjeremylt   @param[out] num_elem Variable to store number of elements
1477a681ae63Sjeremylt 
1478a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1479a681ae63Sjeremylt 
1480b7c9bbdaSJeremy L Thompson   @ref Advanced
1481a681ae63Sjeremylt **/
14822b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, CeedInt *num_elem) {
1483d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
1484e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1485a681ae63Sjeremylt }
1486a681ae63Sjeremylt 
1487a681ae63Sjeremylt /**
1488ca94c3ddSJeremy L Thompson   @brief Get the size of elements in the `CeedElemRestriction`
1489a681ae63Sjeremylt 
1490ca94c3ddSJeremy L Thompson   @param[in]  rstr      `CeedElemRestriction`
1491d1d35e2fSjeremylt   @param[out] elem_size Variable to store size of elements
1492a681ae63Sjeremylt 
1493a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1494a681ae63Sjeremylt 
1495b7c9bbdaSJeremy L Thompson   @ref Advanced
1496a681ae63Sjeremylt **/
14972b730f8bSJeremy L Thompson int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, CeedInt *elem_size) {
1498d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
14992c7e7413SJeremy L Thompson   return CEED_ERROR_SUCCESS;
15002c7e7413SJeremy L Thompson }
15012c7e7413SJeremy L Thompson 
15022c7e7413SJeremy L Thompson /**
150307d5dec1SJeremy L Thompson 
1504725a297dSZach Atkins   @brief Get the number of points in the offsets array for a points `CeedElemRestriction`
150507d5dec1SJeremy L Thompson 
1506ca94c3ddSJeremy L Thompson   @param[in]  rstr       `CeedElemRestriction`
1507725a297dSZach Atkins   @param[out] num_points The number of points in the offsets array
150807d5dec1SJeremy L Thompson 
150907d5dec1SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
151007d5dec1SJeremy L Thompson 
1511c63574e3SJeremy L Thompson   @ref User
151207d5dec1SJeremy L Thompson **/
151307d5dec1SJeremy L Thompson int CeedElemRestrictionGetNumPoints(CeedElemRestriction rstr, CeedInt *num_points) {
15141203703bSJeremy L Thompson   CeedRestrictionType rstr_type;
151507d5dec1SJeremy L Thompson 
15161203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
15176e536b99SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
151807d5dec1SJeremy L Thompson             "Can only retrieve the number of points for a points CeedElemRestriction");
151907d5dec1SJeremy L Thompson 
152007d5dec1SJeremy L Thompson   *num_points = rstr->num_points;
152107d5dec1SJeremy L Thompson   return CEED_ERROR_SUCCESS;
152207d5dec1SJeremy L Thompson }
152307d5dec1SJeremy L Thompson 
152407d5dec1SJeremy L Thompson /**
152507d5dec1SJeremy L Thompson 
1526ca94c3ddSJeremy L Thompson   @brief Get the number of points in an element of a `CeedElemRestriction` at points
152707d5dec1SJeremy L Thompson 
1528ca94c3ddSJeremy L Thompson   @param[in]  rstr       `CeedElemRestriction`
152907d5dec1SJeremy L Thompson   @param[in]  elem       Index number of element to retrieve the number of points for
153007d5dec1SJeremy L Thompson   @param[out] num_points The number of points in the element at index elem
153107d5dec1SJeremy L Thompson 
153207d5dec1SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
153307d5dec1SJeremy L Thompson 
1534c63574e3SJeremy L Thompson   @ref User
153507d5dec1SJeremy L Thompson **/
153607d5dec1SJeremy L Thompson int CeedElemRestrictionGetNumPointsInElement(CeedElemRestriction rstr, CeedInt elem, CeedInt *num_points) {
15371203703bSJeremy L Thompson   CeedRestrictionType rstr_type;
153807d5dec1SJeremy L Thompson   const CeedInt      *offsets;
153907d5dec1SJeremy L Thompson 
15401203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
15416e536b99SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
154207d5dec1SJeremy L Thompson             "Can only retrieve the number of points for a points CeedElemRestriction");
154307d5dec1SJeremy L Thompson 
154407d5dec1SJeremy L Thompson   CeedCall(CeedElemRestrictionGetOffsets(rstr, CEED_MEM_HOST, &offsets));
154507d5dec1SJeremy L Thompson   *num_points = offsets[elem + 1] - offsets[elem];
154607d5dec1SJeremy L Thompson   CeedCall(CeedElemRestrictionRestoreOffsets(rstr, &offsets));
154707d5dec1SJeremy L Thompson   return CEED_ERROR_SUCCESS;
154807d5dec1SJeremy L Thompson }
154907d5dec1SJeremy L Thompson 
155007d5dec1SJeremy L Thompson /**
1551ca94c3ddSJeremy L Thompson   @brief Get the maximum number of points in an element for a `CeedElemRestriction` at points
15522c7e7413SJeremy L Thompson 
1553ca94c3ddSJeremy L Thompson   @param[in]  rstr       `CeedElemRestriction`
15542c7e7413SJeremy L Thompson   @param[out] max_points Variable to store size of elements
15552c7e7413SJeremy L Thompson 
15562c7e7413SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
15572c7e7413SJeremy L Thompson 
15582c7e7413SJeremy L Thompson   @ref Advanced
15592c7e7413SJeremy L Thompson **/
15602c7e7413SJeremy L Thompson int CeedElemRestrictionGetMaxPointsInElement(CeedElemRestriction rstr, CeedInt *max_points) {
15612c7e7413SJeremy L Thompson   CeedInt             num_elem;
15622c7e7413SJeremy L Thompson   CeedRestrictionType rstr_type;
15632c7e7413SJeremy L Thompson 
15642c7e7413SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
15656e536b99SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
15662c7e7413SJeremy L Thompson             "Cannot compute max points for a CeedElemRestriction that does not use points");
15672c7e7413SJeremy L Thompson 
15682c7e7413SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
15692c7e7413SJeremy L Thompson   *max_points = 0;
15702c7e7413SJeremy L Thompson   for (CeedInt e = 0; e < num_elem; e++) {
15712c7e7413SJeremy L Thompson     CeedInt num_points;
15722c7e7413SJeremy L Thompson 
15732c7e7413SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, e, &num_points));
15742c7e7413SJeremy L Thompson     *max_points = CeedIntMax(num_points, *max_points);
15752c7e7413SJeremy L Thompson   }
1576e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1577a681ae63Sjeremylt }
1578a681ae63Sjeremylt 
1579a681ae63Sjeremylt /**
1580ca94c3ddSJeremy L Thompson   @brief Get the size of the l-vector for a `CeedElemRestriction`
1581a681ae63Sjeremylt 
1582ca94c3ddSJeremy L Thompson   @param[in]  rstr   `CeedElemRestriction`
1583701e7d35SJeremy L Thompson   @param[out] l_size Variable to store l-vector size
1584a681ae63Sjeremylt 
1585a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1586a681ae63Sjeremylt 
1587b7c9bbdaSJeremy L Thompson   @ref Advanced
1588a681ae63Sjeremylt **/
15892b730f8bSJeremy L Thompson int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, CeedSize *l_size) {
1590d1d35e2fSjeremylt   *l_size = rstr->l_size;
1591e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1592a681ae63Sjeremylt }
1593a681ae63Sjeremylt 
1594a681ae63Sjeremylt /**
1595701e7d35SJeremy L Thompson   @brief Get the size of the e-vector for a `CeedElemRestriction`
1596701e7d35SJeremy L Thompson 
1597701e7d35SJeremy L Thompson   @param[in]  rstr   `CeedElemRestriction`
1598701e7d35SJeremy L Thompson   @param[out] e_size Variable to store e-vector size
1599701e7d35SJeremy L Thompson 
1600701e7d35SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1601701e7d35SJeremy L Thompson 
1602701e7d35SJeremy L Thompson   @ref Advanced
1603701e7d35SJeremy L Thompson **/
1604701e7d35SJeremy L Thompson int CeedElemRestrictionGetEVectorSize(CeedElemRestriction rstr, CeedSize *e_size) {
1605701e7d35SJeremy L Thompson   *e_size = rstr->e_size;
1606701e7d35SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1607701e7d35SJeremy L Thompson }
1608701e7d35SJeremy L Thompson 
1609701e7d35SJeremy L Thompson /**
1610ca94c3ddSJeremy L Thompson   @brief Get the number of components in the elements of a `CeedElemRestriction`
1611a681ae63Sjeremylt 
1612ca94c3ddSJeremy L Thompson   @param[in]  rstr     `CeedElemRestriction`
1613d1d35e2fSjeremylt   @param[out] num_comp Variable to store number of components
1614a681ae63Sjeremylt 
1615a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1616a681ae63Sjeremylt 
1617b7c9bbdaSJeremy L Thompson   @ref Advanced
1618a681ae63Sjeremylt **/
16192b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, CeedInt *num_comp) {
1620d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
1621e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1622a681ae63Sjeremylt }
1623a681ae63Sjeremylt 
1624a681ae63Sjeremylt /**
1625ca94c3ddSJeremy L Thompson   @brief Get the number of blocks in a `CeedElemRestriction`
1626a681ae63Sjeremylt 
1627ca94c3ddSJeremy L Thompson   @param[in]  rstr      `CeedElemRestriction`
1628d1d35e2fSjeremylt   @param[out] num_block Variable to store number of blocks
1629a681ae63Sjeremylt 
1630a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1631a681ae63Sjeremylt 
1632b7c9bbdaSJeremy L Thompson   @ref Advanced
1633a681ae63Sjeremylt **/
16342b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, CeedInt *num_block) {
1635e7f679fcSJeremy L Thompson   *num_block = rstr->num_block;
1636e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1637a681ae63Sjeremylt }
1638a681ae63Sjeremylt 
1639a681ae63Sjeremylt /**
1640ca94c3ddSJeremy L Thompson   @brief Get the size of blocks in the `CeedElemRestriction`
1641a681ae63Sjeremylt 
1642ca94c3ddSJeremy L Thompson   @param[in]  rstr       `CeedElemRestriction`
1643e7f679fcSJeremy L Thompson   @param[out] block_size Variable to store size of blocks
1644a681ae63Sjeremylt 
1645a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1646a681ae63Sjeremylt 
1647b7c9bbdaSJeremy L Thompson   @ref Advanced
1648a681ae63Sjeremylt **/
1649e7f679fcSJeremy L Thompson int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, CeedInt *block_size) {
1650e7f679fcSJeremy L Thompson   *block_size = rstr->block_size;
1651e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1652a681ae63Sjeremylt }
1653a681ae63Sjeremylt 
1654a681ae63Sjeremylt /**
1655ca94c3ddSJeremy L Thompson   @brief Get the multiplicity of nodes in a `CeedElemRestriction`
16561469ee4dSjeremylt 
1657ca94c3ddSJeremy L Thompson   @param[in]  rstr `CeedElemRestriction`
1658ca94c3ddSJeremy L Thompson   @param[out] mult Vector to store multiplicity (of size `l_size`)
16591469ee4dSjeremylt 
16601469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
16611469ee4dSjeremylt 
16627a982d89SJeremy L. Thompson   @ref User
16631469ee4dSjeremylt **/
16642b730f8bSJeremy L Thompson int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, CeedVector mult) {
1665d1d35e2fSjeremylt   CeedVector e_vec;
16661469ee4dSjeremylt 
166725509ebbSRezgar Shakeri   // Create e_vec to hold intermediate computation in E^T (E 1)
16682b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionCreateVector(rstr, NULL, &e_vec));
16691469ee4dSjeremylt 
167025509ebbSRezgar Shakeri   // Compute e_vec = E * 1
16712b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 1.0));
16722b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, CEED_REQUEST_IMMEDIATE));
167325509ebbSRezgar Shakeri   // Compute multiplicity, mult = E^T * e_vec = E^T (E 1)
16742b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 0.0));
16752b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, CEED_REQUEST_IMMEDIATE));
16761469ee4dSjeremylt   // Cleanup
16772b730f8bSJeremy L Thompson   CeedCall(CeedVectorDestroy(&e_vec));
1678e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
16791469ee4dSjeremylt }
16801469ee4dSjeremylt 
16811469ee4dSjeremylt /**
1682ca94c3ddSJeremy L Thompson   @brief View a `CeedElemRestriction`
1683f02ca4a2SJed Brown 
1684ca94c3ddSJeremy L Thompson   @param[in] rstr   `CeedElemRestriction` to view
1685ca94c3ddSJeremy L Thompson   @param[in] stream Stream to write; typically `stdout` or a file
1686f02ca4a2SJed Brown 
1687f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
1688f02ca4a2SJed Brown 
16897a982d89SJeremy L. Thompson   @ref User
1690f02ca4a2SJed Brown **/
1691f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
16920930e4e7SJeremy L Thompson   CeedRestrictionType rstr_type;
16930930e4e7SJeremy L Thompson 
16940930e4e7SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
16950930e4e7SJeremy L Thompson   if (rstr_type == CEED_RESTRICTION_POINTS) {
16960930e4e7SJeremy L Thompson     CeedInt max_points;
16970930e4e7SJeremy L Thompson 
16980930e4e7SJeremy L Thompson     CeedCall(CeedElemRestrictionGetMaxPointsInElement(rstr, &max_points));
16990930e4e7SJeremy L Thompson     fprintf(stream,
1700249f8407SJeremy L Thompson             "CeedElemRestriction at points from (%" CeedSize_FMT ", %" CeedInt_FMT ") to %" CeedInt_FMT " elements with a maximum of %" CeedInt_FMT
17010930e4e7SJeremy L Thompson             " points on an element\n",
17020930e4e7SJeremy L Thompson             rstr->l_size, rstr->num_comp, rstr->num_elem, max_points);
17030930e4e7SJeremy L Thompson   } else {
1704249f8407SJeremy L Thompson     char strides_str[500];
17051c66c397SJeremy L Thompson 
17062b730f8bSJeremy L Thompson     if (rstr->strides) {
1707249f8407SJeremy L Thompson       sprintf(strides_str, "[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "]", rstr->strides[0], rstr->strides[1], rstr->strides[2]);
17082b730f8bSJeremy L Thompson     } else {
1709249f8407SJeremy L Thompson       sprintf(strides_str, "%" CeedInt_FMT, rstr->comp_stride);
17102b730f8bSJeremy L Thompson     }
1711249f8407SJeremy L Thompson     fprintf(stream,
1712249f8407SJeremy L Thompson             "%sCeedElemRestriction from (%" CeedSize_FMT ", %" CeedInt_FMT ") to %" CeedInt_FMT " elements with %" CeedInt_FMT
1713249f8407SJeremy L Thompson             " nodes each and %s %s\n",
1714e7f679fcSJeremy L Thompson             rstr->block_size > 1 ? "Blocked " : "", rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
1715249f8407SJeremy L Thompson             rstr->strides ? "strides" : "component stride", strides_str);
17160930e4e7SJeremy L Thompson   }
1717e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1718f02ca4a2SJed Brown }
1719f02ca4a2SJed Brown 
1720f02ca4a2SJed Brown /**
1721ca94c3ddSJeremy L Thompson   @brief Destroy a `CeedElemRestriction`
1722b11c1e72Sjeremylt 
1723ca94c3ddSJeremy L Thompson   @param[in,out] rstr `CeedElemRestriction` to destroy
1724b11c1e72Sjeremylt 
1725b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1726dfdf5a53Sjeremylt 
17277a982d89SJeremy L. Thompson   @ref User
1728b11c1e72Sjeremylt **/
17294ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
1730393ac2cdSJeremy L Thompson   if (!*rstr || *rstr == CEED_ELEMRESTRICTION_NONE || --(*rstr)->ref_count > 0) {
1731ad6481ceSJeremy L Thompson     *rstr = NULL;
1732ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
1733ad6481ceSJeremy L Thompson   }
17346574a04fSJeremy L Thompson   CeedCheck((*rstr)->num_readers == 0, (*rstr)->ceed, CEED_ERROR_ACCESS,
17356574a04fSJeremy L Thompson             "Cannot destroy CeedElemRestriction, a process has read access to the offset data");
1736c17ec2beSJeremy L Thompson 
1737c17ec2beSJeremy L Thompson   // Only destroy backend data once between rstr and unsigned copy
17387c1dbaffSSebastian Grimberg   if ((*rstr)->rstr_base) CeedCall(CeedElemRestrictionDestroy(&(*rstr)->rstr_base));
1739c17ec2beSJeremy L Thompson   else if ((*rstr)->Destroy) CeedCall((*rstr)->Destroy(*rstr));
1740c17ec2beSJeremy L Thompson 
17412b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*rstr)->strides));
17422b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*rstr)->ceed));
17432b730f8bSJeremy L Thompson   CeedCall(CeedFree(rstr));
1744e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1745d7b241e6Sjeremylt }
1746d7b241e6Sjeremylt 
1747d7b241e6Sjeremylt /// @}
1748