xref: /libCEED/interface/ceed-elemrestriction.c (revision a299a25b9879b9b54a5c96c9f88ed0cb403a2fde)
19ba83ac0SJeremy L Thompson // Copyright (c) 2017-2026, 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 
101b0f67a9cSJeremy L Thompson /**
102b0f67a9cSJeremy L Thompson   @brief View a `CeedElemRestriction` passed as a `CeedObject`
103b0f67a9cSJeremy L Thompson 
104b0f67a9cSJeremy L Thompson   @param[in] rstr   `CeedElemRestriction` to view
105b0f67a9cSJeremy L Thompson   @param[in] stream Filestream to write to
106b0f67a9cSJeremy L Thompson 
107b0f67a9cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
108b0f67a9cSJeremy L Thompson 
109b0f67a9cSJeremy L Thompson   @ref Developer
110b0f67a9cSJeremy L Thompson **/
111b0f67a9cSJeremy L Thompson static int CeedElemRestrictionView_Object(CeedObject rstr, FILE *stream) {
112b0f67a9cSJeremy L Thompson   CeedCall(CeedElemRestrictionView((CeedElemRestriction)rstr, stream));
113b0f67a9cSJeremy L Thompson   return CEED_ERROR_SUCCESS;
114b0f67a9cSJeremy L Thompson }
115b0f67a9cSJeremy L Thompson 
1167a982d89SJeremy L. Thompson /// @}
1177a982d89SJeremy L. Thompson 
1187a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1197a982d89SJeremy L. Thompson /// CeedElemRestriction Backend API
1207a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1217a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionBackend
1227a982d89SJeremy L. Thompson /// @{
1237a982d89SJeremy L. Thompson 
1247a982d89SJeremy L. Thompson /**
125ca94c3ddSJeremy L Thompson   @brief Get the type of a `CeedElemRestriction`
126a681ae63Sjeremylt 
127ca94c3ddSJeremy L Thompson   @param[in]  rstr      `CeedElemRestriction`
128fcbe8c06SSebastian Grimberg   @param[out] rstr_type Variable to store restriction type
129fcbe8c06SSebastian Grimberg 
130fcbe8c06SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
131fcbe8c06SSebastian Grimberg 
132fcbe8c06SSebastian Grimberg   @ref Backend
133fcbe8c06SSebastian Grimberg **/
134fcbe8c06SSebastian Grimberg int CeedElemRestrictionGetType(CeedElemRestriction rstr, CeedRestrictionType *rstr_type) {
135fcbe8c06SSebastian Grimberg   *rstr_type = rstr->rstr_type;
136fcbe8c06SSebastian Grimberg   return CEED_ERROR_SUCCESS;
137fcbe8c06SSebastian Grimberg }
138fcbe8c06SSebastian Grimberg 
139fcbe8c06SSebastian Grimberg /**
140ca94c3ddSJeremy L Thompson   @brief Get the strided status of a `CeedElemRestriction`
141fcbe8c06SSebastian Grimberg 
142ca94c3ddSJeremy L Thompson   @param[in]  rstr       `CeedElemRestriction`
143ca94c3ddSJeremy L Thompson   @param[out] is_strided Variable to store strided status
144ca94c3ddSJeremy L Thompson 
145ca94c3ddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
146ca94c3ddSJeremy L Thompson 
147ca94c3ddSJeremy L Thompson   @ref Backend
148fcbe8c06SSebastian Grimberg **/
149fcbe8c06SSebastian Grimberg int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) {
150fcbe8c06SSebastian Grimberg   *is_strided = (rstr->rstr_type == CEED_RESTRICTION_STRIDED);
151fcbe8c06SSebastian Grimberg   return CEED_ERROR_SUCCESS;
152fcbe8c06SSebastian Grimberg }
153fcbe8c06SSebastian Grimberg 
154fcbe8c06SSebastian Grimberg /**
155ca94c3ddSJeremy L Thompson   @brief Get the points status of a `CeedElemRestriction`
1563ac8f562SJeremy L Thompson 
157ca94c3ddSJeremy L Thompson   @param[in]  rstr      `CeedElemRestriction`
158ca94c3ddSJeremy L Thompson   @param[out] is_points Variable to store points status
159ca94c3ddSJeremy L Thompson 
160ca94c3ddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
161ca94c3ddSJeremy L Thompson 
162ca94c3ddSJeremy L Thompson   @ref Backend
1633ac8f562SJeremy L Thompson **/
164637baffdSJeremy L Thompson int CeedElemRestrictionIsAtPoints(CeedElemRestriction rstr, bool *is_points) {
1653ac8f562SJeremy L Thompson   *is_points = (rstr->rstr_type == CEED_RESTRICTION_POINTS);
1663ac8f562SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1673ac8f562SJeremy L Thompson }
1683ac8f562SJeremy L Thompson 
1693ac8f562SJeremy L Thompson /**
170ca94c3ddSJeremy L Thompson   @brief Check if two `CeedElemRestriction` created with @ref CeedElemRestrictionCreateAtPoints() and use the same points per element
17148acf710SJeremy L Thompson 
172ca94c3ddSJeremy L Thompson   @param[in]  rstr_a         First `CeedElemRestriction`
173ca94c3ddSJeremy L Thompson   @param[in]  rstr_b         Second `CeedElemRestriction`
17448acf710SJeremy L Thompson   @param[out] are_compatible Variable to store compatibility status
175ca94c3ddSJeremy L Thompson 
176ca94c3ddSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
177ca94c3ddSJeremy L Thompson 
178ca94c3ddSJeremy L Thompson   @ref Backend
17948acf710SJeremy L Thompson **/
18048acf710SJeremy L Thompson int CeedElemRestrictionAtPointsAreCompatible(CeedElemRestriction rstr_a, CeedElemRestriction rstr_b, bool *are_compatible) {
18148acf710SJeremy L Thompson   CeedInt num_elem_a, num_elem_b, num_points_a, num_points_b;
18248acf710SJeremy L Thompson 
18348acf710SJeremy L Thompson   // Cannot compare non-points restrictions
1849bc66399SJeremy L Thompson   CeedCheck(rstr_a->rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr_a), CEED_ERROR_UNSUPPORTED,
1859bc66399SJeremy L Thompson             "First CeedElemRestriction must be AtPoints");
1869bc66399SJeremy L Thompson   CeedCheck(rstr_b->rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr_a), CEED_ERROR_UNSUPPORTED,
1879bc66399SJeremy L Thompson             "Second CeedElemRestriction must be AtPoints");
18848acf710SJeremy L Thompson 
18948acf710SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr_a, &num_elem_a));
19048acf710SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr_b, &num_elem_b));
19148acf710SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumPoints(rstr_a, &num_points_a));
19248acf710SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumPoints(rstr_b, &num_points_b));
19348acf710SJeremy L Thompson 
19448acf710SJeremy L Thompson   // Check size and contents of offsets arrays
19548acf710SJeremy L Thompson   *are_compatible = true;
19648acf710SJeremy L Thompson   if (num_elem_a != num_elem_b) *are_compatible = false;
19748acf710SJeremy L Thompson   if (num_points_a != num_points_b) *are_compatible = false;
19848acf710SJeremy L Thompson   if (*are_compatible) {
19948acf710SJeremy L Thompson     const CeedInt *offsets_a, *offsets_b;
20048acf710SJeremy L Thompson 
20148acf710SJeremy L Thompson     CeedCall(CeedElemRestrictionGetOffsets(rstr_a, CEED_MEM_HOST, &offsets_a));
20248acf710SJeremy L Thompson     CeedCall(CeedElemRestrictionGetOffsets(rstr_b, CEED_MEM_HOST, &offsets_b));
20348acf710SJeremy L Thompson     for (CeedInt i = 0; i < num_elem_a + 1 + num_points_a; i++) *are_compatible &= offsets_a[i] == offsets_b[i];
20448acf710SJeremy L Thompson     CeedCall(CeedElemRestrictionRestoreOffsets(rstr_a, &offsets_a));
20548acf710SJeremy L Thompson     CeedCall(CeedElemRestrictionRestoreOffsets(rstr_b, &offsets_b));
20648acf710SJeremy L Thompson   }
20748acf710SJeremy L Thompson   return CEED_ERROR_SUCCESS;
20848acf710SJeremy L Thompson }
20948acf710SJeremy L Thompson 
21048acf710SJeremy L Thompson /**
211ca94c3ddSJeremy L Thompson   @brief Get the strides of a strided `CeedElemRestriction`
2127a982d89SJeremy L. Thompson 
213ca94c3ddSJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
214a681ae63Sjeremylt   @param[out] strides Variable to store strides array
2157a982d89SJeremy L. Thompson 
2167a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2177a982d89SJeremy L. Thompson 
2187a982d89SJeremy L. Thompson   @ref Backend
2197a982d89SJeremy L. Thompson **/
22056c48462SJeremy L Thompson int CeedElemRestrictionGetStrides(CeedElemRestriction rstr, CeedInt strides[3]) {
2216e536b99SJeremy L Thompson   CeedCheck(rstr->strides, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, "CeedElemRestriction has no stride data");
22256c48462SJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) strides[i] = rstr->strides[i];
223e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2247a982d89SJeremy L. Thompson }
2257a982d89SJeremy L. Thompson 
2267a982d89SJeremy L. Thompson /**
227ca94c3ddSJeremy L Thompson   @brief Get the backend stride status of a `CeedElemRestriction`
22877d1c127SSebastian Grimberg 
229ca94c3ddSJeremy L Thompson   @param[in]  rstr                 `CeedElemRestriction`
23077d1c127SSebastian Grimberg   @param[out] has_backend_strides  Variable to store stride status
23177d1c127SSebastian Grimberg 
23277d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
23377d1c127SSebastian Grimberg 
23477d1c127SSebastian Grimberg   @ref Backend
23577d1c127SSebastian Grimberg **/
23677d1c127SSebastian Grimberg int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, bool *has_backend_strides) {
2376e536b99SJeremy L Thompson   CeedCheck(rstr->strides, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, "CeedElemRestriction has no stride data");
23877d1c127SSebastian Grimberg   *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
23977d1c127SSebastian Grimberg                           (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
24077d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
24177d1c127SSebastian Grimberg }
24277d1c127SSebastian Grimberg 
24377d1c127SSebastian Grimberg /**
244ca94c3ddSJeremy L Thompson   @brief Get read-only access to a `CeedElemRestriction` offsets array by @ref CeedMemType
245bd33150aSjeremylt 
246ca94c3ddSJeremy L Thompson   @param[in]  rstr     `CeedElemRestriction` to retrieve offsets
247fcbe8c06SSebastian Grimberg   @param[in]  mem_type Memory type on which to access the array.
248fcbe8c06SSebastian Grimberg                          If the backend uses a different memory type, this will perform a copy (possibly cached).
249ca94c3ddSJeremy L Thompson   @param[out] offsets  Array on memory type `mem_type`
250bd33150aSjeremylt 
251bd33150aSjeremylt   @return An error code: 0 - success, otherwise - failure
252bd33150aSjeremylt 
253bd33150aSjeremylt   @ref User
254bd33150aSjeremylt **/
2552b730f8bSJeremy L Thompson int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) {
2567c1dbaffSSebastian Grimberg   if (rstr->rstr_base) {
2577c1dbaffSSebastian Grimberg     CeedCall(CeedElemRestrictionGetOffsets(rstr->rstr_base, mem_type, offsets));
258c17ec2beSJeremy L Thompson   } else {
2596e536b99SJeremy L Thompson     CeedCheck(rstr->GetOffsets, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED,
2601ef3a2a9SJeremy L Thompson               "Backend does not implement CeedElemRestrictionGetOffsets");
2612b730f8bSJeremy L Thompson     CeedCall(rstr->GetOffsets(rstr, mem_type, offsets));
262d1d35e2fSjeremylt     rstr->num_readers++;
263c17ec2beSJeremy L Thompson   }
264e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
265430758c8SJeremy L Thompson }
266430758c8SJeremy L Thompson 
267430758c8SJeremy L Thompson /**
268ca94c3ddSJeremy L Thompson   @brief Restore an offsets array obtained using @ref CeedElemRestrictionGetOffsets()
269430758c8SJeremy L Thompson 
270ca94c3ddSJeremy L Thompson   @param[in] rstr    `CeedElemRestriction` to restore
271ea61e9acSJeremy L Thompson   @param[in] offsets Array of offset data
272430758c8SJeremy L Thompson 
273430758c8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
274430758c8SJeremy L Thompson 
275430758c8SJeremy L Thompson   @ref User
276430758c8SJeremy L Thompson **/
2772b730f8bSJeremy L Thompson int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr, const CeedInt **offsets) {
2787c1dbaffSSebastian Grimberg   if (rstr->rstr_base) {
2797c1dbaffSSebastian Grimberg     CeedCall(CeedElemRestrictionRestoreOffsets(rstr->rstr_base, offsets));
280c17ec2beSJeremy L Thompson   } else {
281430758c8SJeremy L Thompson     *offsets = NULL;
282d1d35e2fSjeremylt     rstr->num_readers--;
283c17ec2beSJeremy L Thompson   }
284e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
285bd33150aSjeremylt }
286bd33150aSjeremylt 
287bd33150aSjeremylt /**
288ca94c3ddSJeremy L Thompson   @brief Get read-only access to a `CeedElemRestriction` orientations array by @ref CeedMemType
2893ac43b2cSJeremy L Thompson 
290ca94c3ddSJeremy L Thompson   @param[in]  rstr     `CeedElemRestriction` to retrieve orientations
291fcbe8c06SSebastian Grimberg   @param[in]  mem_type Memory type on which to access the array.
292fcbe8c06SSebastian Grimberg                          If the backend uses a different memory type, this will perform a copy (possibly cached).
293ca94c3ddSJeremy L Thompson   @param[out] orients  Array on memory type `mem_type`
2943ac43b2cSJeremy L Thompson 
2953ac43b2cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2963ac43b2cSJeremy L Thompson 
29777d1c127SSebastian Grimberg   @ref User
2983ac43b2cSJeremy L Thompson **/
29977d1c127SSebastian Grimberg int CeedElemRestrictionGetOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const bool **orients) {
3006e536b99SJeremy L Thompson   CeedCheck(rstr->GetOrientations, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED,
3011ef3a2a9SJeremy L Thompson             "Backend does not implement CeedElemRestrictionGetOrientations");
30277d1c127SSebastian Grimberg   CeedCall(rstr->GetOrientations(rstr, mem_type, orients));
30377d1c127SSebastian Grimberg   rstr->num_readers++;
304e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3053ac43b2cSJeremy L Thompson }
3063ac43b2cSJeremy L Thompson 
3073ac43b2cSJeremy L Thompson /**
308ca94c3ddSJeremy L Thompson   @brief Restore an orientations array obtained using @ref CeedElemRestrictionGetOrientations()
309b435c5a6Srezgarshakeri 
310ca94c3ddSJeremy L Thompson   @param[in] rstr    `CeedElemRestriction` to restore
31177d1c127SSebastian Grimberg   @param[in] orients Array of orientation data
312b435c5a6Srezgarshakeri 
313b435c5a6Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
314b435c5a6Srezgarshakeri 
31577d1c127SSebastian Grimberg   @ref User
316b435c5a6Srezgarshakeri **/
31777d1c127SSebastian Grimberg int CeedElemRestrictionRestoreOrientations(CeedElemRestriction rstr, const bool **orients) {
31877d1c127SSebastian Grimberg   *orients = NULL;
31977d1c127SSebastian Grimberg   rstr->num_readers--;
320b435c5a6Srezgarshakeri   return CEED_ERROR_SUCCESS;
321b435c5a6Srezgarshakeri }
322b435c5a6Srezgarshakeri 
323b435c5a6Srezgarshakeri /**
324ca94c3ddSJeremy L Thompson   @brief Get read-only access to a `CeedElemRestriction` curl-conforming orientations array by @ref CeedMemType
3257a982d89SJeremy L. Thompson 
326ca94c3ddSJeremy L Thompson   @param[in]  rstr         `CeedElemRestriction` to retrieve curl-conforming orientations
327fcbe8c06SSebastian Grimberg   @param[in]  mem_type     Memory type on which to access the array.
328fcbe8c06SSebastian Grimberg                              If the backend uses a different memory type, this will perform a copy (possibly cached).
329ca94c3ddSJeremy L Thompson   @param[out] curl_orients Array on memory type `mem_type`
3307a982d89SJeremy L. Thompson 
3317a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3327a982d89SJeremy L. Thompson 
33377d1c127SSebastian Grimberg   @ref User
3347a982d89SJeremy L. Thompson **/
3350c73c039SSebastian Grimberg int CeedElemRestrictionGetCurlOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt8 **curl_orients) {
3366e536b99SJeremy L Thompson   CeedCheck(rstr->GetCurlOrientations, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED,
3371ef3a2a9SJeremy L Thompson             "Backend does not implement CeedElemRestrictionGetCurlOrientations");
33877d1c127SSebastian Grimberg   CeedCall(rstr->GetCurlOrientations(rstr, mem_type, curl_orients));
33977d1c127SSebastian Grimberg   rstr->num_readers++;
34077d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
34177d1c127SSebastian Grimberg }
34277d1c127SSebastian Grimberg 
34377d1c127SSebastian Grimberg /**
344ca94c3ddSJeremy L Thompson   @brief Restore an orientations array obtained using @ref CeedElemRestrictionGetCurlOrientations()
34577d1c127SSebastian Grimberg 
346ca94c3ddSJeremy L Thompson   @param[in] rstr         `CeedElemRestriction` to restore
34777d1c127SSebastian Grimberg   @param[in] curl_orients Array of orientation data
34877d1c127SSebastian Grimberg 
34977d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
35077d1c127SSebastian Grimberg 
35177d1c127SSebastian Grimberg   @ref User
35277d1c127SSebastian Grimberg **/
3530c73c039SSebastian Grimberg int CeedElemRestrictionRestoreCurlOrientations(CeedElemRestriction rstr, const CeedInt8 **curl_orients) {
35477d1c127SSebastian Grimberg   *curl_orients = NULL;
35577d1c127SSebastian Grimberg   rstr->num_readers--;
356e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3577a982d89SJeremy L. Thompson }
3587a982d89SJeremy L. Thompson 
3597a982d89SJeremy L. Thompson /**
36049fd234cSJeremy L Thompson 
36122eb1385SJeremy L Thompson   @brief Get the L-vector layout of a strided `CeedElemRestriction`
36222eb1385SJeremy L Thompson 
36322eb1385SJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
36422eb1385SJeremy L Thompson   @param[out] layout  Variable to store layout array, stored as `[nodes, components, elements]`.
36522eb1385SJeremy 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]`.
36622eb1385SJeremy L Thompson 
36722eb1385SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
36822eb1385SJeremy L Thompson 
36922eb1385SJeremy L Thompson   @ref Backend
37022eb1385SJeremy L Thompson **/
37156c48462SJeremy L Thompson int CeedElemRestrictionGetLLayout(CeedElemRestriction rstr, CeedInt layout[3]) {
37222eb1385SJeremy L Thompson   bool                has_backend_strides;
37322eb1385SJeremy L Thompson   CeedRestrictionType rstr_type;
37422eb1385SJeremy L Thompson 
37522eb1385SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
3769bc66399SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_STRIDED, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR,
3779bc66399SJeremy L Thompson             "Only strided CeedElemRestriction have strided L-vector layout");
37822eb1385SJeremy L Thompson   CeedCall(CeedElemRestrictionHasBackendStrides(rstr, &has_backend_strides));
37922eb1385SJeremy L Thompson   if (has_backend_strides) {
3809bc66399SJeremy L Thompson     CeedCheck(rstr->l_layout[0], CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, "CeedElemRestriction has no L-vector layout data");
38156c48462SJeremy L Thompson     for (CeedInt i = 0; i < 3; i++) layout[i] = rstr->l_layout[i];
38222eb1385SJeremy L Thompson   } else {
38322eb1385SJeremy L Thompson     CeedCall(CeedElemRestrictionGetStrides(rstr, layout));
38422eb1385SJeremy L Thompson   }
38522eb1385SJeremy L Thompson   return CEED_ERROR_SUCCESS;
38622eb1385SJeremy L Thompson }
38722eb1385SJeremy L Thompson 
38822eb1385SJeremy L Thompson /**
38922eb1385SJeremy L Thompson 
39022eb1385SJeremy L Thompson   @brief Set the L-vector layout of a strided `CeedElemRestriction`
39122eb1385SJeremy L Thompson 
39222eb1385SJeremy L Thompson   @param[in] rstr   `CeedElemRestriction`
39322eb1385SJeremy L Thompson   @param[in] layout Variable to containing layout array, stored as `[nodes, components, elements]`.
39422eb1385SJeremy 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]`.
39522eb1385SJeremy L Thompson 
39622eb1385SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
39722eb1385SJeremy L Thompson 
39822eb1385SJeremy L Thompson   @ref Backend
39922eb1385SJeremy L Thompson **/
40022eb1385SJeremy L Thompson int CeedElemRestrictionSetLLayout(CeedElemRestriction rstr, CeedInt layout[3]) {
40122eb1385SJeremy L Thompson   CeedRestrictionType rstr_type;
40222eb1385SJeremy L Thompson 
40322eb1385SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
4046e536b99SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_STRIDED, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR,
4056e536b99SJeremy L Thompson             "Only strided CeedElemRestriction have strided L-vector layout");
40622eb1385SJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) rstr->l_layout[i] = layout[i];
40722eb1385SJeremy L Thompson   return CEED_ERROR_SUCCESS;
40822eb1385SJeremy L Thompson }
40922eb1385SJeremy L Thompson 
41022eb1385SJeremy L Thompson /**
41122eb1385SJeremy L Thompson 
412ca94c3ddSJeremy L Thompson   @brief Get the E-vector layout of a `CeedElemRestriction`
41349fd234cSJeremy L Thompson 
414ca94c3ddSJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
415ca94c3ddSJeremy L Thompson   @param[out] layout  Variable to store layout array, stored as `[nodes, components, elements]`.
416ca94c3ddSJeremy L Thompson                         The data for node `i`, component `j`, element `k` in the E-vector is given by `i*layout[0] + j*layout[1] + k*layout[2]`.
41749fd234cSJeremy L Thompson 
41849fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
41949fd234cSJeremy L Thompson 
42049fd234cSJeremy L Thompson   @ref Backend
42149fd234cSJeremy L Thompson **/
42256c48462SJeremy L Thompson int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
4236e536b99SJeremy L Thompson   CeedCheck(rstr->e_layout[0], CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, "CeedElemRestriction has no E-vector layout data");
42456c48462SJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) layout[i] = rstr->e_layout[i];
425e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
42649fd234cSJeremy L Thompson }
42749fd234cSJeremy L Thompson 
42849fd234cSJeremy L Thompson /**
42949fd234cSJeremy L Thompson 
430ca94c3ddSJeremy L Thompson   @brief Set the E-vector layout of a `CeedElemRestriction`
43149fd234cSJeremy L Thompson 
432ca94c3ddSJeremy L Thompson   @param[in] rstr   `CeedElemRestriction`
433ca94c3ddSJeremy L Thompson   @param[in] layout Variable to containing layout array, stored as `[nodes, components, elements]`.
434ca94c3ddSJeremy 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]`.
43549fd234cSJeremy L Thompson 
43649fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
43749fd234cSJeremy L Thompson 
43849fd234cSJeremy L Thompson   @ref Backend
43949fd234cSJeremy L Thompson **/
4402b730f8bSJeremy L Thompson int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
44122eb1385SJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) rstr->e_layout[i] = layout[i];
442e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
44349fd234cSJeremy L Thompson }
44449fd234cSJeremy L Thompson 
44549fd234cSJeremy L Thompson /**
44619605835SJeremy L Thompson 
44719605835SJeremy L Thompson   @brief Get the E-vector element offset of a `CeedElemRestriction` at points
44819605835SJeremy L Thompson 
44919605835SJeremy L Thompson   @param[in]  rstr        `CeedElemRestriction`
45019605835SJeremy L Thompson   @param[in]  elem        Element number index into E-vector for
45119605835SJeremy L Thompson   @param[out] elem_offset Offset for element `elem` in the E-vector.
45219605835SJeremy 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`.
45319605835SJeremy L Thompson 
45419605835SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
45519605835SJeremy L Thompson 
45619605835SJeremy L Thompson   @ref Backend
45719605835SJeremy L Thompson **/
45819605835SJeremy L Thompson int CeedElemRestrictionGetAtPointsElementOffset(CeedElemRestriction rstr, CeedInt elem, CeedSize *elem_offset) {
45919605835SJeremy L Thompson   CeedInt             num_comp;
46019605835SJeremy L Thompson   CeedRestrictionType rstr_type;
46119605835SJeremy L Thompson 
46219605835SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
46319605835SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
46419605835SJeremy L Thompson             "Can only compute offset for a points CeedElemRestriction");
46519605835SJeremy L Thompson 
46619605835SJeremy L Thompson   // Backend method
46719605835SJeremy L Thompson   if (rstr->GetAtPointsElementOffset) {
46819605835SJeremy L Thompson     CeedCall(rstr->GetAtPointsElementOffset(rstr, elem, elem_offset));
46919605835SJeremy L Thompson     return CEED_ERROR_SUCCESS;
47019605835SJeremy L Thompson   }
47119605835SJeremy L Thompson 
47219605835SJeremy L Thompson   // Default layout (CPU)
47319605835SJeremy L Thompson   *elem_offset = 0;
47419605835SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
47519605835SJeremy L Thompson   for (CeedInt i = 0; i < elem; i++) {
47619605835SJeremy L Thompson     CeedInt num_points;
47719605835SJeremy L Thompson 
47819605835SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, i, &num_points));
47919605835SJeremy L Thompson     *elem_offset += num_points * num_comp;
48019605835SJeremy L Thompson   }
48119605835SJeremy L Thompson   return CEED_ERROR_SUCCESS;
48219605835SJeremy L Thompson }
48319605835SJeremy L Thompson 
48419605835SJeremy L Thompson /**
485ff1bc20eSJeremy L Thompson 
486ff1bc20eSJeremy L Thompson   @brief Set the E-vector size of a `CeedElemRestriction` at points
487ff1bc20eSJeremy L Thompson 
488ff1bc20eSJeremy L Thompson   @param[in,out]  rstr   `CeedElemRestriction`
489ff1bc20eSJeremy L Thompson   @param[in]      e_size New E-vector size; must be longer than the current E-vector size
490ff1bc20eSJeremy L Thompson 
491ff1bc20eSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
492ff1bc20eSJeremy L Thompson 
493ff1bc20eSJeremy L Thompson   @ref Backend
494ff1bc20eSJeremy L Thompson **/
495ff1bc20eSJeremy L Thompson int CeedElemRestrictionSetAtPointsEVectorSize(CeedElemRestriction rstr, CeedSize e_size) {
496ff1bc20eSJeremy L Thompson   CeedRestrictionType rstr_type;
497ff1bc20eSJeremy L Thompson 
498ff1bc20eSJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
4999bc66399SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
5009bc66399SJeremy L Thompson             "Can only compute offset for a points CeedElemRestriction");
5019bc66399SJeremy L Thompson   CeedCheck(e_size >= rstr->e_size, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
5023f08121cSJeremy L Thompson             "Can only increase the size of the E-vector for the CeedElemRestriction."
5033f08121cSJeremy L Thompson             " Current size: %" CeedSize_FMT " New size: %" CeedSize_FMT,
5043f08121cSJeremy L Thompson             rstr->e_size, e_size);
505ff1bc20eSJeremy L Thompson   rstr->e_size = e_size;
506ff1bc20eSJeremy L Thompson   return CEED_ERROR_SUCCESS;
507ff1bc20eSJeremy L Thompson }
508ff1bc20eSJeremy L Thompson 
509ff1bc20eSJeremy L Thompson /**
510ca94c3ddSJeremy L Thompson   @brief Get the backend data of a `CeedElemRestriction`
5117a982d89SJeremy L. Thompson 
512ca94c3ddSJeremy L Thompson   @param[in]  rstr `CeedElemRestriction`
5137a982d89SJeremy L. Thompson   @param[out] data Variable to store data
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 CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) {
520777ff853SJeremy L Thompson   *(void **)data = rstr->data;
521e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5227a982d89SJeremy L. Thompson }
5237a982d89SJeremy L. Thompson 
5247a982d89SJeremy L. Thompson /**
525ca94c3ddSJeremy L Thompson   @brief Set the backend data of a `CeedElemRestriction`
5267a982d89SJeremy L. Thompson 
527ca94c3ddSJeremy L Thompson   @param[in,out] rstr `CeedElemRestriction`
528ea61e9acSJeremy L Thompson   @param[in]     data Data to set
5297a982d89SJeremy L. Thompson 
5307a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
5317a982d89SJeremy L. Thompson 
5327a982d89SJeremy L. Thompson   @ref Backend
5337a982d89SJeremy L. Thompson **/
534777ff853SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) {
535777ff853SJeremy L Thompson   rstr->data = data;
536e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5377a982d89SJeremy L. Thompson }
5387a982d89SJeremy L. Thompson 
53934359f16Sjeremylt /**
540ca94c3ddSJeremy L Thompson   @brief Increment the reference counter for a `CeedElemRestriction`
54134359f16Sjeremylt 
542ca94c3ddSJeremy L Thompson   @param[in,out] rstr `CeedElemRestriction` to increment the reference counter
54334359f16Sjeremylt 
54434359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
54534359f16Sjeremylt 
54634359f16Sjeremylt   @ref Backend
54734359f16Sjeremylt **/
5489560d06aSjeremylt int CeedElemRestrictionReference(CeedElemRestriction rstr) {
549b0f67a9cSJeremy L Thompson   CeedCall(CeedObjectReference((CeedObject)rstr));
55034359f16Sjeremylt   return CEED_ERROR_SUCCESS;
55134359f16Sjeremylt }
55234359f16Sjeremylt 
5536e15d496SJeremy L Thompson /**
554ca94c3ddSJeremy L Thompson   @brief Estimate number of FLOPs required to apply `CeedElemRestriction` in `t_mode`
5556e15d496SJeremy L Thompson 
556ca94c3ddSJeremy L Thompson   @param[in]  rstr   `CeedElemRestriction` to estimate FLOPs for
557ea61e9acSJeremy L Thompson   @param[in]  t_mode Apply restriction or transpose
558ea61e9acSJeremy L Thompson   @param[out] flops  Address of variable to hold FLOPs estimate
5596e15d496SJeremy L Thompson 
5606e15d496SJeremy L Thompson   @ref Backend
5616e15d496SJeremy L Thompson **/
5622b730f8bSJeremy L Thompson int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedSize *flops) {
5631203703bSJeremy L Thompson   CeedSize            e_size, scale = 0;
56489edb9e3SSebastian Grimberg   CeedRestrictionType rstr_type;
5651c66c397SJeremy L Thompson 
5661203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &e_size));
56789edb9e3SSebastian Grimberg   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
56877d1c127SSebastian Grimberg   if (t_mode == CEED_TRANSPOSE) {
56989edb9e3SSebastian Grimberg     switch (rstr_type) {
5703ac8f562SJeremy L Thompson       case CEED_RESTRICTION_POINTS:
5713ac8f562SJeremy L Thompson         scale = 0;
5723ac8f562SJeremy L Thompson         break;
57389edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STRIDED:
57489edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STANDARD:
57577d1c127SSebastian Grimberg         scale = 1;
57689edb9e3SSebastian Grimberg         break;
57789edb9e3SSebastian Grimberg       case CEED_RESTRICTION_ORIENTED:
57877d1c127SSebastian Grimberg         scale = 2;
57989edb9e3SSebastian Grimberg         break;
58089edb9e3SSebastian Grimberg       case CEED_RESTRICTION_CURL_ORIENTED:
58177d1c127SSebastian Grimberg         scale = 6;
58289edb9e3SSebastian Grimberg         break;
5836e15d496SJeremy L Thompson     }
58477d1c127SSebastian Grimberg   } else {
58589edb9e3SSebastian Grimberg     switch (rstr_type) {
58689edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STRIDED:
58789edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STANDARD:
5883ac8f562SJeremy L Thompson       case CEED_RESTRICTION_POINTS:
58977d1c127SSebastian Grimberg         scale = 0;
59089edb9e3SSebastian Grimberg         break;
59189edb9e3SSebastian Grimberg       case CEED_RESTRICTION_ORIENTED:
59277d1c127SSebastian Grimberg         scale = 1;
59389edb9e3SSebastian Grimberg         break;
59489edb9e3SSebastian Grimberg       case CEED_RESTRICTION_CURL_ORIENTED:
59577d1c127SSebastian Grimberg         scale = 5;
59689edb9e3SSebastian Grimberg         break;
59777d1c127SSebastian Grimberg     }
59877d1c127SSebastian Grimberg   }
5996e15d496SJeremy L Thompson   *flops = e_size * scale;
6006e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6016e15d496SJeremy L Thompson }
6026e15d496SJeremy L Thompson 
6037a982d89SJeremy L. Thompson /// @}
6047a982d89SJeremy L. Thompson 
60515910d16Sjeremylt /// @cond DOXYGEN_SKIP
60615910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
60715910d16Sjeremylt /// @endcond
60815910d16Sjeremylt 
6097a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
6107a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
6117a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
6127a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
613d7b241e6Sjeremylt /// @{
614d7b241e6Sjeremylt 
6157a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
61645f1e315Sjeremylt const CeedInt CEED_STRIDES_BACKEND[3] = {0};
6177a982d89SJeremy L. Thompson 
618ca94c3ddSJeremy L Thompson /// Argument for @ref CeedOperatorSetField() indicating that the field does not require a `CeedElemRestriction`
6192b730f8bSJeremy L Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = &ceed_elemrestriction_none;
6207a982d89SJeremy L. Thompson 
621d7b241e6Sjeremylt /**
622ca94c3ddSJeremy L Thompson   @brief Create a `CeedElemRestriction`
623d7b241e6Sjeremylt 
624ca94c3ddSJeremy L Thompson   @param[in]  ceed        `Ceed` context used to create the `CeedElemRestriction`
625ca94c3ddSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the `offsets` array
626ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
627ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
628fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
629ca94c3ddSJeremy 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`.
630fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
631fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
632ca94c3ddSJeremy L Thompson   @param[in]  mem_type    Memory type of the `offsets` array, see @ref CeedMemType
633ca94c3ddSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the `offsets` array, see @ref CeedCopyMode
634ca94c3ddSJeremy L Thompson   @param[in]  offsets     Array of shape `[num_elem, elem_size]`.
635ca94c3ddSJeremy 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.
636ca94c3ddSJeremy L Thompson                             All offsets must be in the range `[0, l_size - 1]`.
637ca94c3ddSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created `CeedElemRestriction` will be stored
638d7b241e6Sjeremylt 
639b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
640dfdf5a53Sjeremylt 
6417a982d89SJeremy L. Thompson   @ref User
642b11c1e72Sjeremylt **/
6432b730f8bSJeremy L Thompson int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
6442b730f8bSJeremy L Thompson                               CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
6455fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
6465fe0d4faSjeremylt     Ceed delegate;
6476574a04fSJeremy L Thompson 
6482b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
649ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreate");
6502b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
6519bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
652e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6535fe0d4faSjeremylt   }
6545fe0d4faSjeremylt 
655e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
6566574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
657ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
658ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
659e022e1f8SJeremy L Thompson 
6602b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
661b0f67a9cSJeremy L Thompson   CeedCall(CeedObjectCreate(ceed, CeedElemRestrictionView_Object, &(*rstr)->obj));
662d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
663d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
664d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
665d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
666d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
6671203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp;
668e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
669e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
67061a27d74SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_STANDARD;
671fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, NULL, *rstr));
672e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
673d7b241e6Sjeremylt }
674d7b241e6Sjeremylt 
675d7b241e6Sjeremylt /**
676ca94c3ddSJeremy L Thompson   @brief Create a `CeedElemRestriction` with orientation signs
677fc0567d9Srezgarshakeri 
678ca94c3ddSJeremy L Thompson   @param[in]  ceed        `Ceed` context used to create the `CeedElemRestriction`
679ca94c3ddSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the `offsets` array
680ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
681ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
682fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
683ca94c3ddSJeremy 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`.
684fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
685fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
686ca94c3ddSJeremy L Thompson   @param[in]  mem_type    Memory type of the `offsets` array, see @ref CeedMemType
687ca94c3ddSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the `offsets` array, see @ref CeedCopyMode
688ca94c3ddSJeremy L Thompson   @param[in]  offsets     Array of shape `[num_elem, elem_size]`.
689ca94c3ddSJeremy 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`.
690ca94c3ddSJeremy L Thompson                             All offsets must be in the range `[0, l_size - 1]`.
691ca94c3ddSJeremy L Thompson   @param[in]  orients     Boolean array of shape `[num_elem, elem_size]` with `false` for positively oriented and `true` to flip the orientation
692ca94c3ddSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created `CeedElemRestriction` will be stored
693fc0567d9Srezgarshakeri 
694fc0567d9Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
695fc0567d9Srezgarshakeri 
696fc0567d9Srezgarshakeri   @ref User
697fc0567d9Srezgarshakeri **/
6982b730f8bSJeremy L Thompson int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
69977d1c127SSebastian Grimberg                                       CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orients,
700fc0567d9Srezgarshakeri                                       CeedElemRestriction *rstr) {
701fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreate) {
702fc0567d9Srezgarshakeri     Ceed delegate;
7036574a04fSJeremy L Thompson 
7042b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
705ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateOriented");
7061a8516d0SJames Wright     CeedCall(CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, orients,
7071a8516d0SJames Wright                                                rstr));
7089bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
709fc0567d9Srezgarshakeri     return CEED_ERROR_SUCCESS;
710fc0567d9Srezgarshakeri   }
711fc0567d9Srezgarshakeri 
712e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
7136574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
714ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
715ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
716e022e1f8SJeremy L Thompson 
7172b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
718b0f67a9cSJeremy L Thompson   CeedCall(CeedObjectCreate(ceed, CeedElemRestrictionView_Object, &(*rstr)->obj));
719fc0567d9Srezgarshakeri   (*rstr)->num_elem    = num_elem;
720fc0567d9Srezgarshakeri   (*rstr)->elem_size   = elem_size;
721fc0567d9Srezgarshakeri   (*rstr)->num_comp    = num_comp;
722fc0567d9Srezgarshakeri   (*rstr)->comp_stride = comp_stride;
723fc0567d9Srezgarshakeri   (*rstr)->l_size      = l_size;
7241203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp;
725e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
726e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
727fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_ORIENTED;
728fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, orients, NULL, *rstr));
72977d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
73077d1c127SSebastian Grimberg }
73177d1c127SSebastian Grimberg 
73277d1c127SSebastian Grimberg /**
733ca94c3ddSJeremy L Thompson   @brief Create a `CeedElemRestriction` with a general tridiagonal transformation matrix for curl-conforming elements
73477d1c127SSebastian Grimberg 
735ca94c3ddSJeremy L Thompson   @param[in]  ceed         `Ceed` context used to create the `CeedElemRestriction`
736ca94c3ddSJeremy L Thompson   @param[in]  num_elem     Number of elements described in the `offsets` array
73777d1c127SSebastian Grimberg   @param[in]  elem_size    Size (number of "nodes") per element
73877d1c127SSebastian Grimberg   @param[in]  num_comp     Number of field components per interpolation node (1 for scalar fields)
739fcbe8c06SSebastian Grimberg   @param[in]  comp_stride  Stride between components for the same L-vector "node".
740ca94c3ddSJeremy 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`.
741fcbe8c06SSebastian Grimberg   @param[in]  l_size       The size of the L-vector.
742fcbe8c06SSebastian Grimberg                              This vector may be larger than the elements and fields given by this restriction.
743ca94c3ddSJeremy L Thompson   @param[in]  mem_type     Memory type of the `offsets` array, see @ref CeedMemType
744ca94c3ddSJeremy L Thompson   @param[in]  copy_mode    Copy mode for the `offsets` array, see @ref CeedCopyMode
745ca94c3ddSJeremy L Thompson   @param[in]  offsets      Array of shape `[num_elem, elem_size]`.
746ca94c3ddSJeremy 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`.
747ca94c3ddSJeremy L Thompson                              All offsets must be in the range `[0, l_size - 1]`.
748ca94c3ddSJeremy 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.
749ca94c3ddSJeremy 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).
750ca94c3ddSJeremy L Thompson   @param[out] rstr         Address of the variable where the newly created `CeedElemRestriction` will be stored
75177d1c127SSebastian Grimberg 
75277d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
75377d1c127SSebastian Grimberg 
75477d1c127SSebastian Grimberg   @ref User
75577d1c127SSebastian Grimberg **/
75677d1c127SSebastian Grimberg int CeedElemRestrictionCreateCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
7570c73c039SSebastian Grimberg                                           CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const CeedInt8 *curl_orients,
75877d1c127SSebastian Grimberg                                           CeedElemRestriction *rstr) {
759fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreate) {
76077d1c127SSebastian Grimberg     Ceed delegate;
76177d1c127SSebastian Grimberg 
76277d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
763ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateCurlOriented");
76477d1c127SSebastian Grimberg     CeedCall(CeedElemRestrictionCreateCurlOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
76577d1c127SSebastian Grimberg                                                    curl_orients, rstr));
7669bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
76777d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
76877d1c127SSebastian Grimberg   }
76977d1c127SSebastian Grimberg 
770e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
77177d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
772ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
773ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
77477d1c127SSebastian Grimberg 
77577d1c127SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
776b0f67a9cSJeremy L Thompson   CeedCall(CeedObjectCreate(ceed, CeedElemRestrictionView_Object, &(*rstr)->obj));
77777d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
77877d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
77977d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
78077d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
78177d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
7821203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp;
783e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
784e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
785fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_CURL_ORIENTED;
786fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, curl_orients, *rstr));
787fc0567d9Srezgarshakeri   return CEED_ERROR_SUCCESS;
788fc0567d9Srezgarshakeri }
789fc0567d9Srezgarshakeri 
790fc0567d9Srezgarshakeri /**
791ca94c3ddSJeremy L Thompson   @brief Create a strided `CeedElemRestriction`
792d7b241e6Sjeremylt 
793ca94c3ddSJeremy L Thompson   @param[in]  ceed      `Ceed` context used to create the `CeedElemRestriction`
794ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
795ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
796ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation "node" (1 for scalar fields)
797fcbe8c06SSebastian Grimberg   @param[in]  l_size    The size of the L-vector.
798fcbe8c06SSebastian Grimberg                           This vector may be larger than the elements and fields given by this restriction.
799ca94c3ddSJeremy L Thompson   @param[in]  strides   Array for strides between `[nodes, components, elements]`.
800ca94c3ddSJeremy 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]`.
801ca94c3ddSJeremy L Thompson                           @ref CEED_STRIDES_BACKEND may be used for `CeedVector` ordered by the same `Ceed` backend.
802972f909dSJeremy L Thompson                           `CEED_STRIDES_BACKEND` should only be used pass data between `CeedOperator` created with the same `Ceed` backend.
803972f909dSJeremy L Thompson                           The L-vector layout will, in general, be different between `Ceed` backends.
804ca94c3ddSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created `CeedElemRestriction` will be stored
805d7b241e6Sjeremylt 
806b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
807dfdf5a53Sjeremylt 
8087a982d89SJeremy L. Thompson   @ref User
809b11c1e72Sjeremylt **/
8102b730f8bSJeremy L Thompson int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedSize l_size, const CeedInt strides[3],
811f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
8125fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
8135fe0d4faSjeremylt     Ceed delegate;
814b04eb3d9SSebastian Grimberg 
8152b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
816ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateStrided");
8172b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, l_size, strides, rstr));
8189bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
819e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
8205fe0d4faSjeremylt   }
8215fe0d4faSjeremylt 
822e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
8236574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
824ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
825aa72de07SJeremy L Thompson   CeedCheck(l_size >= (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp, ceed, CEED_ERROR_DIMENSION,
826870ea2d9SJeremy L Thompson             "L-vector size must be at least num_elem * elem_size * num_comp. Expected: > %" CeedSize_FMT " Found: %" CeedSize_FMT,
827870ea2d9SJeremy L Thompson             (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp, l_size);
828e022e1f8SJeremy L Thompson 
8292b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
830b0f67a9cSJeremy L Thompson   CeedCall(CeedObjectCreate(ceed, CeedElemRestrictionView_Object, &(*rstr)->obj));
831d1d35e2fSjeremylt   (*rstr)->num_elem   = num_elem;
832d1d35e2fSjeremylt   (*rstr)->elem_size  = elem_size;
833d1d35e2fSjeremylt   (*rstr)->num_comp   = num_comp;
834d1d35e2fSjeremylt   (*rstr)->l_size     = l_size;
8351203703bSJeremy L Thompson   (*rstr)->e_size     = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp;
836e7f679fcSJeremy L Thompson   (*rstr)->num_block  = num_elem;
837e7f679fcSJeremy L Thompson   (*rstr)->block_size = 1;
838fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type  = CEED_RESTRICTION_STRIDED;
8392b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
8402b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
841fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
842e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
843d7b241e6Sjeremylt }
844d7b241e6Sjeremylt 
845d7b241e6Sjeremylt /**
846ca94c3ddSJeremy 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.
8473ac8f562SJeremy L Thompson 
8483ac8f562SJeremy L Thompson   The offsets array is arranged as
8493ac8f562SJeremy L Thompson 
8503ac8f562SJeremy L Thompson   element_0_start_index
8513ac8f562SJeremy L Thompson   element_1_start_index
8523ac8f562SJeremy L Thompson   ...
8533ac8f562SJeremy L Thompson   element_n_start_index
8543ac8f562SJeremy L Thompson   element_n_stop_index
8553ac8f562SJeremy L Thompson   element_0_point_0
8563ac8f562SJeremy L Thompson   element_0_point_1
8573ac8f562SJeremy L Thompson   ...
8583ac8f562SJeremy L Thompson 
859ca94c3ddSJeremy L Thompson   @param[in]  ceed       `Ceed` context used to create the `CeedElemRestriction`
860ca94c3ddSJeremy L Thompson   @param[in]  num_elem   Number of elements described in the `offsets` array
861ca94c3ddSJeremy L Thompson   @param[in]  num_points Number of points described in the `offsets` array
8623ac8f562SJeremy L Thompson   @param[in]  num_comp   Number of field components per interpolation node (1 for scalar fields).
8633ac8f562SJeremy L Thompson                            Components are assumed to be contiguous by point.
8643ac8f562SJeremy L Thompson   @param[in]  l_size     The size of the L-vector.
8653ac8f562SJeremy L Thompson                            This vector may be larger than the elements and fields given by this restriction.
866ca94c3ddSJeremy L Thompson   @param[in]  mem_type   Memory type of the `offsets` array, see @ref CeedMemType
867ca94c3ddSJeremy L Thompson   @param[in]  copy_mode  Copy mode for the `offsets` array, see @ref CeedCopyMode
868ca94c3ddSJeremy L Thompson   @param[in]  offsets    Array of size `num_elem + 1 + num_points`.
8693ac8f562SJeremy L Thompson                            The first portion of the offsets array holds the ranges of indices corresponding to each element.
8703ac8f562SJeremy L Thompson                            The second portion holds the indices for each element.
871ca94c3ddSJeremy L Thompson   @param[out] rstr       Address of the variable where the newly created `CeedElemRestriction` will be stored
8723ac8f562SJeremy L Thompson 
8733ac8f562SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
8743ac8f562SJeremy L Thompson 
8753ac8f562SJeremy L Thompson   @ref Backend
8763ac8f562SJeremy L Thompson  **/
8773ac8f562SJeremy L Thompson int CeedElemRestrictionCreateAtPoints(Ceed ceed, CeedInt num_elem, CeedInt num_points, CeedInt num_comp, CeedSize l_size, CeedMemType mem_type,
8783ac8f562SJeremy L Thompson                                       CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
8793ac8f562SJeremy L Thompson   if (!ceed->ElemRestrictionCreateAtPoints) {
8803ac8f562SJeremy L Thompson     Ceed delegate;
8813ac8f562SJeremy L Thompson 
8823ac8f562SJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
883ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateAtPoints");
8843ac8f562SJeremy L Thompson     CeedCall(CeedElemRestrictionCreateAtPoints(delegate, num_elem, num_points, num_comp, l_size, mem_type, copy_mode, offsets, rstr));
8859bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
8863ac8f562SJeremy L Thompson     return CEED_ERROR_SUCCESS;
8873ac8f562SJeremy L Thompson   }
8883ac8f562SJeremy L Thompson 
8893ac8f562SJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
8903ac8f562SJeremy L Thompson   CeedCheck(num_points >= 0, ceed, CEED_ERROR_DIMENSION, "Number of points must be non-negative");
891ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
892870ea2d9SJeremy L Thompson   CeedCheck(l_size >= (CeedSize)num_points * num_comp, ceed, CEED_ERROR_DIMENSION,
893870ea2d9SJeremy L Thompson             "L-vector must be at least num_points * num_comp. Expected: > %" CeedSize_FMT " Found: %" CeedSize_FMT, (CeedSize)num_points * num_comp,
894870ea2d9SJeremy L Thompson             l_size);
8953ac8f562SJeremy L Thompson 
8963ac8f562SJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
897b0f67a9cSJeremy L Thompson   CeedCall(CeedObjectCreate(ceed, CeedElemRestrictionView_Object, &(*rstr)->obj));
8983ac8f562SJeremy L Thompson   (*rstr)->num_elem    = num_elem;
8993ac8f562SJeremy L Thompson   (*rstr)->num_points  = num_points;
9003ac8f562SJeremy L Thompson   (*rstr)->num_comp    = num_comp;
9012c2c926cSJeremy L Thompson   (*rstr)->comp_stride = 1;
9023ac8f562SJeremy L Thompson   (*rstr)->l_size      = l_size;
9031203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_points * (CeedSize)num_comp;
90405fa913cSJeremy L Thompson   (*rstr)->num_block   = num_elem;
9053ac8f562SJeremy L Thompson   (*rstr)->block_size  = 1;
9063ac8f562SJeremy L Thompson   (*rstr)->rstr_type   = CEED_RESTRICTION_POINTS;
9073ac8f562SJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateAtPoints(mem_type, copy_mode, offsets, NULL, NULL, *rstr));
9083ac8f562SJeremy L Thompson   return CEED_ERROR_SUCCESS;
9093ac8f562SJeremy L Thompson }
9103ac8f562SJeremy L Thompson 
9113ac8f562SJeremy L Thompson /**
912ca94c3ddSJeremy L Thompson   @brief Create a blocked `CeedElemRestriction`, typically only used by backends
913d7b241e6Sjeremylt 
914ca94c3ddSJeremy L Thompson   @param[in]  ceed        `Ceed` context used to create the `CeedElemRestriction`
915ca94c3ddSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the `offsets` array
916ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of unknowns) per element
917e7f679fcSJeremy L Thompson   @param[in]  block_size  Number of elements in a block
918ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
919fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
920ca94c3ddSJeremy L Thompson                             Data for node `i`, component `j`, element `k` can be found in the L-vector at index `offsets[i + k*elem_size] + j*comp_stride`.
921fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
922fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
923ca94c3ddSJeremy L Thompson   @param[in]  mem_type    Memory type of the `offsets` array, see @ref CeedMemType
924ca94c3ddSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the `offsets` array, see @ref CeedCopyMode
925ca94c3ddSJeremy L Thompson   @param[in]  offsets     Array of shape `[num_elem, elem_size]`.
926ca94c3ddSJeremy L Thompson                             Row `i` holds the ordered list of the offsets (into the input `CeedVector`) for the unknowns corresponding to element `i`, where `0 <= i < num_elem`.
927ca94c3ddSJeremy L Thompson                             All offsets must be in the range `[0, l_size - 1]`.
928ca94c3ddSJeremy L Thompson                             The backend will permute and pad this array to the desired ordering for the blocksize, which is typically given by the backend.
929ca94c3ddSJeremy L Thompson                             The default reordering is to interlace elements.
930ca94c3ddSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created `CeedElemRestriction` will be stored
931d7b241e6Sjeremylt 
932b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
933dfdf5a53Sjeremylt 
9347a982d89SJeremy L. Thompson   @ref Backend
935b11c1e72Sjeremylt  **/
936e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedInt comp_stride,
9372b730f8bSJeremy L Thompson                                      CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets,
9384ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
9391c66c397SJeremy L Thompson   CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
940d7b241e6Sjeremylt 
9415fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
9425fe0d4faSjeremylt     Ceed delegate;
9436574a04fSJeremy L Thompson 
9442b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
945ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlocked");
946e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
947e7f679fcSJeremy L Thompson                                               rstr));
9489bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
949e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
9505fe0d4faSjeremylt   }
951d7b241e6Sjeremylt 
952e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
9536574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
954e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
955ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
956ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
957e022e1f8SJeremy L Thompson 
958e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
959e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
960d7b241e6Sjeremylt 
961db002c03SJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
962b0f67a9cSJeremy L Thompson   CeedCall(CeedObjectCreate(ceed, CeedElemRestrictionView_Object, &(*rstr)->obj));
963d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
964d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
965d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
966d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
967d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
9681203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
969e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
970e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
97161a27d74SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_STANDARD;
972e7f679fcSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL, NULL, *rstr));
9731c66c397SJeremy L Thompson   if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
974e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
975d7b241e6Sjeremylt }
976d7b241e6Sjeremylt 
977b11c1e72Sjeremylt /**
978ca94c3ddSJeremy L Thompson   @brief Create a blocked oriented `CeedElemRestriction`, typically only used by backends
97977d1c127SSebastian Grimberg 
980ca94c3ddSJeremy L Thompson   @param[in]  ceed        `Ceed` context used to create the `CeedElemRestriction`
981ca94c3ddSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the `offsets` array.
98277d1c127SSebastian Grimberg   @param[in]  elem_size   Size (number of unknowns) per element
983e7f679fcSJeremy L Thompson   @param[in]  block_size  Number of elements in a block
98477d1c127SSebastian Grimberg   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
985fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
986ca94c3ddSJeremy 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`.
987fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
988fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
989ca94c3ddSJeremy L Thompson   @param[in]  mem_type    Memory type of the `offsets` array, see @ref CeedMemType
990ca94c3ddSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the `offsets` array, see @ref CeedCopyMode
991ca94c3ddSJeremy L Thompson   @param[in]  offsets     Array of shape `[num_elem, elem_size]`.
992ca94c3ddSJeremy 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`.
993ca94c3ddSJeremy L Thompson                             All offsets must be in the range `[0, l_size - 1]`.
994ca94c3ddSJeremy L Thompson                             The backend will permute and pad this array to the desired ordering for the blocksize, which is typically given by the backend.
995ca94c3ddSJeremy L Thompson                             The default reordering is to interlace elements.
996ca94c3ddSJeremy L Thompson   @param[in]  orients     Boolean array of shape `[num_elem, elem_size]` with `false` for positively oriented and `true` to flip the orientation.
997ca94c3ddSJeremy L Thompson                             Will also be permuted and padded similarly to `offsets`.
998ca94c3ddSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created `CeedElemRestriction` will be stored
99977d1c127SSebastian Grimberg 
100077d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
100177d1c127SSebastian Grimberg 
100277d1c127SSebastian Grimberg   @ref Backend
100377d1c127SSebastian Grimberg  **/
1004e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp,
1005e7f679fcSJeremy L Thompson                                              CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode,
1006e7f679fcSJeremy L Thompson                                              const CeedInt *offsets, const bool *orients, CeedElemRestriction *rstr) {
1007e7f679fcSJeremy L Thompson   bool    *block_orients;
10081c66c397SJeremy L Thompson   CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
100977d1c127SSebastian Grimberg 
1010fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreateBlocked) {
101177d1c127SSebastian Grimberg     Ceed delegate;
101277d1c127SSebastian Grimberg 
101377d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
1014ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedOriented");
1015e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode,
101677d1c127SSebastian Grimberg                                                       offsets, orients, rstr));
10179bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
101877d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
101977d1c127SSebastian Grimberg   }
102077d1c127SSebastian Grimberg 
102177d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
1022e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
1023ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
1024ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
102577d1c127SSebastian Grimberg 
1026e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
1027e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_orients));
1028e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
1029e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOrients(orients, block_orients, num_block, num_elem, block_size, elem_size));
103077d1c127SSebastian Grimberg 
1031fcbe8c06SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
1032b0f67a9cSJeremy L Thompson   CeedCall(CeedObjectCreate(ceed, CeedElemRestrictionView_Object, &(*rstr)->obj));
103377d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
103477d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
103577d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
103677d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
103777d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
10381203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1039e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
1040e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
1041fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_ORIENTED;
10421a8516d0SJames Wright   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, (const bool *)block_orients, NULL,
10431a8516d0SJames Wright                                               *rstr));
10441c66c397SJeremy L Thompson   if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
104577d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
104677d1c127SSebastian Grimberg }
104777d1c127SSebastian Grimberg 
104877d1c127SSebastian Grimberg /**
1049ca94c3ddSJeremy L Thompson   @brief Create a blocked curl-oriented `CeedElemRestriction`, typically only used by backends
105077d1c127SSebastian Grimberg 
1051ca94c3ddSJeremy L Thompson   @param[in]  ceed         `Ceed` context used to create the `CeedElemRestriction`
1052ca94c3ddSJeremy L Thompson   @param[in]  num_elem     Number of elements described in the `offsets` array.
105377d1c127SSebastian Grimberg   @param[in]  elem_size    Size (number of unknowns) per element
1054e7f679fcSJeremy L Thompson   @param[in]  block_size   Number of elements in a block
105577d1c127SSebastian Grimberg   @param[in]  num_comp     Number of field components per interpolation node (1 for scalar fields)
1056fcbe8c06SSebastian Grimberg   @param[in]  comp_stride  Stride between components for the same L-vector "node".
1057ca94c3ddSJeremy 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`.
1058fcbe8c06SSebastian Grimberg   @param[in]  l_size       The size of the L-vector.
1059fcbe8c06SSebastian Grimberg                              This vector may be larger than the elements and fields given by this restriction.
1060ca94c3ddSJeremy L Thompson   @param[in]  mem_type     Memory type of the `offsets` array, see @ref CeedMemType
1061ca94c3ddSJeremy L Thompson   @param[in]  copy_mode    Copy mode for the `offsets` array, see @ref CeedCopyMode
1062ca94c3ddSJeremy L Thompson   @param[in]  offsets      Array of shape `[num_elem, elem_size]`.
1063ca94c3ddSJeremy 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`.
1064ca94c3ddSJeremy L Thompson                              All offsets must be in the range `[0, l_size - 1]`.
1065ca94c3ddSJeremy L Thompson                              The backend will permute and pad this array to the desired  ordering for the blocksize, which is typically given by the backend.
1066ca94c3ddSJeremy L Thompson                              The default reordering is to interlace elements.
1067ca94c3ddSJeremy 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.
1068ca94c3ddSJeremy 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).
1069ca94c3ddSJeremy L Thompson                              Will also be permuted and padded similarly to offsets.
1070ca94c3ddSJeremy L Thompson   @param[out] rstr         Address of the variable where the newly created `CeedElemRestriction` will be stored
107177d1c127SSebastian Grimberg 
107277d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
107377d1c127SSebastian Grimberg 
107477d1c127SSebastian Grimberg   @ref Backend
107577d1c127SSebastian Grimberg  **/
1076e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp,
107777d1c127SSebastian Grimberg                                                  CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode,
10780c73c039SSebastian Grimberg                                                  const CeedInt *offsets, const CeedInt8 *curl_orients, CeedElemRestriction *rstr) {
1079e7f679fcSJeremy L Thompson   CeedInt8 *block_curl_orients;
10801c66c397SJeremy L Thompson   CeedInt  *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
108177d1c127SSebastian Grimberg 
1082fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreateBlocked) {
108377d1c127SSebastian Grimberg     Ceed delegate;
108477d1c127SSebastian Grimberg 
108577d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
1086ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedCurlOriented");
1087e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedCurlOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type,
1088e7f679fcSJeremy L Thompson                                                           copy_mode, offsets, curl_orients, rstr));
10899bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
109077d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
109177d1c127SSebastian Grimberg   }
109277d1c127SSebastian Grimberg 
1093e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
109477d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
1095e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
1096ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
1097ca94c3ddSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1");
109877d1c127SSebastian Grimberg 
1099e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
1100e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * 3 * elem_size, &block_curl_orients));
1101e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
1102e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadCurlOrients(curl_orients, block_curl_orients, num_block, num_elem, block_size, 3 * elem_size));
110377d1c127SSebastian Grimberg 
1104fcbe8c06SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
1105b0f67a9cSJeremy L Thompson   CeedCall(CeedObjectCreate(ceed, CeedElemRestrictionView_Object, &(*rstr)->obj));
110677d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
110777d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
110877d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
110977d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
111077d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
11111203703bSJeremy L Thompson   (*rstr)->e_size      = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1112e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
1113e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
1114fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_CURL_ORIENTED;
1115e7f679fcSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL,
1116e7f679fcSJeremy L Thompson                                               (const CeedInt8 *)block_curl_orients, *rstr));
11171c66c397SJeremy L Thompson   if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
111877d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
111977d1c127SSebastian Grimberg }
112077d1c127SSebastian Grimberg 
112177d1c127SSebastian Grimberg /**
1122ca94c3ddSJeremy L Thompson   @brief Create a blocked strided `CeedElemRestriction`, typically only used by backends
11237509a596Sjeremylt 
1124ca94c3ddSJeremy L Thompson   @param[in]  ceed        `Ceed` context used to create the `CeedElemRestriction`
1125ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described by the restriction
1126ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
1127e7f679fcSJeremy L Thompson   @param[in]  block_size  Number of elements in a block
1128ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
1129fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
1130fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
1131ca94c3ddSJeremy L Thompson   @param[in]  strides     Array for strides between `[nodes, components, elements]`.
1132ca94c3ddSJeremy 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]`.
1133ca94c3ddSJeremy L Thompson                             @ref CEED_STRIDES_BACKEND may be used for `CeedVector` ordered by the same `Ceed` backend.
1134ca94c3ddSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created `CeedElemRestriction` will be stored
11357509a596Sjeremylt 
11367509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
11377509a596Sjeremylt 
11387a982d89SJeremy L. Thompson   @ref User
11397509a596Sjeremylt **/
1140e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedSize l_size,
11418621c6c6SJeremy L Thompson                                             const CeedInt strides[3], CeedElemRestriction *rstr) {
1142e7f679fcSJeremy L Thompson   CeedInt num_block = (num_elem / block_size) + !!(num_elem % block_size);
11437509a596Sjeremylt 
11447509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
11457509a596Sjeremylt     Ceed delegate;
11466574a04fSJeremy L Thompson 
11472b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
1148ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedStrided");
1149e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, block_size, num_comp, l_size, strides, rstr));
11509bc66399SJeremy L Thompson     CeedCall(CeedDestroy(&delegate));
1151e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
11527509a596Sjeremylt   }
11537509a596Sjeremylt 
1154e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
11556574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
1156e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
1157ca94c3ddSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component");
1158aa72de07SJeremy L Thompson   CeedCheck(l_size >= (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp, ceed, CEED_ERROR_DIMENSION,
1159870ea2d9SJeremy L Thompson             "L-vector size must be at least num_elem * elem_size * num_comp. Expected: > %" CeedSize_FMT " Found: %" CeedSize_FMT,
1160870ea2d9SJeremy L Thompson             (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp, l_size);
1161e022e1f8SJeremy L Thompson 
11622b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
1163b0f67a9cSJeremy L Thompson   CeedCall(CeedObjectCreate(ceed, CeedElemRestrictionView_Object, &(*rstr)->obj));
1164d1d35e2fSjeremylt   (*rstr)->num_elem   = num_elem;
1165d1d35e2fSjeremylt   (*rstr)->elem_size  = elem_size;
1166d1d35e2fSjeremylt   (*rstr)->num_comp   = num_comp;
1167d1d35e2fSjeremylt   (*rstr)->l_size     = l_size;
11681203703bSJeremy L Thompson   (*rstr)->e_size     = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1169e7f679fcSJeremy L Thompson   (*rstr)->num_block  = num_block;
1170e7f679fcSJeremy L Thompson   (*rstr)->block_size = block_size;
1171fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type  = CEED_RESTRICTION_STRIDED;
11722b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
11732b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
1174fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
1175e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
11767509a596Sjeremylt }
11777509a596Sjeremylt 
11787509a596Sjeremylt /**
1179ca94c3ddSJeremy L Thompson   @brief Copy the pointer to a `CeedElemRestriction` and set @ref CeedElemRestrictionApply() implementation to use the unsigned version.
1180c17ec2beSJeremy L Thompson 
1181ca94c3ddSJeremy L Thompson   Both pointers should be destroyed with @ref CeedElemRestrictionDestroy().
1182c17ec2beSJeremy L Thompson 
1183ca94c3ddSJeremy L Thompson   @param[in]     rstr          `CeedElemRestriction` to create unsigned reference to
1184ca94c3ddSJeremy L Thompson   @param[in,out] rstr_unsigned Variable to store unsigned `CeedElemRestriction`
1185c17ec2beSJeremy L Thompson 
1186c17ec2beSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1187c17ec2beSJeremy L Thompson 
1188c17ec2beSJeremy L Thompson   @ref User
1189c17ec2beSJeremy L Thompson **/
1190c17ec2beSJeremy L Thompson int CeedElemRestrictionCreateUnsignedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unsigned) {
1191c17ec2beSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr_unsigned));
1192c17ec2beSJeremy L Thompson 
1193c17ec2beSJeremy L Thompson   // Copy old rstr
1194c17ec2beSJeremy L Thompson   memcpy(*rstr_unsigned, rstr, sizeof(struct CeedElemRestriction_private));
1195b0f67a9cSJeremy L Thompson   CeedCall(CeedObjectCreate(CeedElemRestrictionReturnCeed(rstr), CeedElemRestrictionView_Object, &(*rstr_unsigned)->obj));
1196c17ec2beSJeremy L Thompson   (*rstr_unsigned)->strides = NULL;
1197c17ec2beSJeremy L Thompson   if (rstr->strides) {
1198c17ec2beSJeremy L Thompson     CeedCall(CeedMalloc(3, &(*rstr_unsigned)->strides));
1199c17ec2beSJeremy L Thompson     for (CeedInt i = 0; i < 3; i++) (*rstr_unsigned)->strides[i] = rstr->strides[i];
1200c17ec2beSJeremy L Thompson   }
12017c1dbaffSSebastian Grimberg   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unsigned)->rstr_base));
1202c17ec2beSJeremy L Thompson 
1203c17ec2beSJeremy L Thompson   // Override Apply
1204c17ec2beSJeremy L Thompson   (*rstr_unsigned)->Apply = rstr->ApplyUnsigned;
1205c17ec2beSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1206c17ec2beSJeremy L Thompson }
1207c17ec2beSJeremy L Thompson 
1208c17ec2beSJeremy L Thompson /**
1209ca94c3ddSJeremy L Thompson   @brief Copy the pointer to a `CeedElemRestriction` and set @ref CeedElemRestrictionApply() implementation to use the unoriented version.
12107c1dbaffSSebastian Grimberg 
1211ca94c3ddSJeremy L Thompson   Both pointers should be destroyed with @ref CeedElemRestrictionDestroy().
12127c1dbaffSSebastian Grimberg 
1213ca94c3ddSJeremy L Thompson   @param[in]     rstr            `CeedElemRestriction` to create unoriented reference to
1214ca94c3ddSJeremy L Thompson   @param[in,out] rstr_unoriented Variable to store unoriented `CeedElemRestriction`
12157c1dbaffSSebastian Grimberg 
12167c1dbaffSSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
12177c1dbaffSSebastian Grimberg 
12187c1dbaffSSebastian Grimberg   @ref User
12197c1dbaffSSebastian Grimberg **/
12207c1dbaffSSebastian Grimberg int CeedElemRestrictionCreateUnorientedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unoriented) {
12217c1dbaffSSebastian Grimberg   CeedCall(CeedCalloc(1, rstr_unoriented));
12227c1dbaffSSebastian Grimberg 
12237c1dbaffSSebastian Grimberg   // Copy old rstr
12247c1dbaffSSebastian Grimberg   memcpy(*rstr_unoriented, rstr, sizeof(struct CeedElemRestriction_private));
1225b0f67a9cSJeremy L Thompson   CeedCall(CeedObjectCreate(CeedElemRestrictionReturnCeed(rstr), CeedElemRestrictionView_Object, &(*rstr_unoriented)->obj));
12267c1dbaffSSebastian Grimberg   (*rstr_unoriented)->strides = NULL;
12277c1dbaffSSebastian Grimberg   if (rstr->strides) {
12287c1dbaffSSebastian Grimberg     CeedCall(CeedMalloc(3, &(*rstr_unoriented)->strides));
12297c1dbaffSSebastian Grimberg     for (CeedInt i = 0; i < 3; i++) (*rstr_unoriented)->strides[i] = rstr->strides[i];
12307c1dbaffSSebastian Grimberg   }
12317c1dbaffSSebastian Grimberg   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unoriented)->rstr_base));
12327c1dbaffSSebastian Grimberg 
12337c1dbaffSSebastian Grimberg   // Override Apply
12347c1dbaffSSebastian Grimberg   (*rstr_unoriented)->Apply = rstr->ApplyUnoriented;
12357c1dbaffSSebastian Grimberg   return CEED_ERROR_SUCCESS;
12367c1dbaffSSebastian Grimberg }
12377c1dbaffSSebastian Grimberg 
12387c1dbaffSSebastian Grimberg /**
1239ca94c3ddSJeremy L Thompson   @brief Copy the pointer to a `CeedElemRestriction`.
12409fd66db6SSebastian Grimberg 
1241ca94c3ddSJeremy L Thompson   Both pointers should be destroyed with @ref CeedElemRestrictionDestroy().
12429560d06aSjeremylt 
1243ca94c3ddSJeremy 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`.
1244ca94c3ddSJeremy L Thompson         This `CeedElemRestriction` will be destroyed if `*rstr_copy` is the only reference to this `CeedElemRestriction`.
1245ea61e9acSJeremy L Thompson 
1246ca94c3ddSJeremy L Thompson   @param[in]     rstr      `CeedElemRestriction` to copy reference to
1247ea61e9acSJeremy L Thompson   @param[in,out] rstr_copy Variable to store copied reference
12489560d06aSjeremylt 
12499560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
12509560d06aSjeremylt 
12519560d06aSjeremylt   @ref User
12529560d06aSjeremylt **/
12532b730f8bSJeremy L Thompson int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_copy) {
1254393ac2cdSJeremy L Thompson   if (rstr != CEED_ELEMRESTRICTION_NONE) CeedCall(CeedElemRestrictionReference(rstr));
12552b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionDestroy(rstr_copy));
12569560d06aSjeremylt   *rstr_copy = rstr;
12579560d06aSjeremylt   return CEED_ERROR_SUCCESS;
12589560d06aSjeremylt }
12599560d06aSjeremylt 
12609560d06aSjeremylt /**
1261ca94c3ddSJeremy L Thompson   @brief Create `CeedVector` associated with a `CeedElemRestriction`
1262b11c1e72Sjeremylt 
1263ca94c3ddSJeremy L Thompson   @param[in]  rstr  `CeedElemRestriction`
1264ca94c3ddSJeremy L Thompson   @param[out] l_vec The address of the L-vector to be created, or `NULL`
1265ca94c3ddSJeremy L Thompson   @param[out] e_vec The address of the E-vector to be created, or `NULL`
1266b11c1e72Sjeremylt 
1267b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1268dfdf5a53Sjeremylt 
12697a982d89SJeremy L. Thompson   @ref User
1270b11c1e72Sjeremylt **/
12712b730f8bSJeremy L Thompson int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, CeedVector *e_vec) {
1272d2643443SJeremy L Thompson   CeedSize e_size, l_size;
12731203703bSJeremy L Thompson   Ceed     ceed;
127448acf710SJeremy L Thompson 
12751203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
12761203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &l_size));
12771203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &e_size));
12781203703bSJeremy L Thompson   if (l_vec) CeedCall(CeedVectorCreate(ceed, l_size, l_vec));
12791203703bSJeremy L Thompson   if (e_vec) CeedCall(CeedVectorCreate(ceed, e_size, e_vec));
12809bc66399SJeremy L Thompson   CeedCall(CeedDestroy(&ceed));
1281e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1282d7b241e6Sjeremylt }
1283d7b241e6Sjeremylt 
1284d7b241e6Sjeremylt /**
1285d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
1286d7b241e6Sjeremylt 
1287ca94c3ddSJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
1288ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1289ca94c3ddSJeremy L Thompson   @param[in]  u       Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE)
1290ca94c3ddSJeremy L Thompson   @param[out] ru      Output vector (of shape `[num_elem * elem_size]` when `t_mode` = @ref CEED_NOTRANSPOSE).
1291fcbe8c06SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
1292ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
1293b11c1e72Sjeremylt 
1294b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1295dfdf5a53Sjeremylt 
12967a982d89SJeremy L. Thompson   @ref User
1297b11c1e72Sjeremylt **/
12982b730f8bSJeremy L Thompson int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
1299701e7d35SJeremy L Thompson   CeedSize min_u_len, min_ru_len, len;
1300701e7d35SJeremy L Thompson   CeedInt  num_elem;
1301d7b241e6Sjeremylt 
1302d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
1303701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &min_ru_len));
1304701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_u_len));
1305d7b241e6Sjeremylt   } else {
1306701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &min_u_len));
1307701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_ru_len));
1308d7b241e6Sjeremylt   }
1309701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(u, &len));
13109bc66399SJeremy L Thompson   CeedCheck(min_u_len <= len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
1311701e7d35SJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_ru_len,
1312701e7d35SJeremy L Thompson             min_u_len);
1313701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(ru, &len));
13149bc66399SJeremy L Thompson   CeedCheck(min_ru_len <= len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
1315701e7d35SJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_u_len,
1316701e7d35SJeremy L Thompson             min_ru_len);
1317701e7d35SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
1318701e7d35SJeremy L Thompson   if (num_elem > 0) CeedCall(rstr->Apply(rstr, t_mode, u, ru, request));
1319e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1320d7b241e6Sjeremylt }
1321d7b241e6Sjeremylt 
1322d7b241e6Sjeremylt /**
13233ac8f562SJeremy L Thompson   @brief Restrict an L-vector of points to a single element or apply its transpose
13243ac8f562SJeremy L Thompson 
1325ca94c3ddSJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
1326ca94c3ddSJeremy L Thompson   @param[in]  elem    Element number in range `[0, num_elem)`
13273ac8f562SJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1328ca94c3ddSJeremy L Thompson   @param[in]  u       Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE)
1329ca94c3ddSJeremy L Thompson   @param[out] ru      Output vector (of shape [`num_points * num_comp]` when `t_mode` = @ref CEED_NOTRANSPOSE).
13303ac8f562SJeremy L Thompson                         Ordering of the e-vector is decided by the backend.
13313ac8f562SJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
13323ac8f562SJeremy L Thompson 
13333ac8f562SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
13343ac8f562SJeremy L Thompson 
13353ac8f562SJeremy L Thompson   @ref User
13363ac8f562SJeremy L Thompson **/
133705fa913cSJeremy L Thompson int CeedElemRestrictionApplyAtPointsInElement(CeedElemRestriction rstr, CeedInt elem, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
13383ac8f562SJeremy L Thompson                                               CeedRequest *request) {
1339701e7d35SJeremy L Thompson   CeedSize min_u_len, min_ru_len, len;
1340701e7d35SJeremy L Thompson   CeedInt  num_elem;
13413ac8f562SJeremy L Thompson 
13429bc66399SJeremy L Thompson   CeedCheck(rstr->ApplyAtPointsInElement, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED,
13439bc66399SJeremy L Thompson             "Backend does not implement CeedElemRestrictionApplyAtPointsInElement");
13441ef3a2a9SJeremy L Thompson 
13453ac8f562SJeremy L Thompson   if (t_mode == CEED_NOTRANSPOSE) {
1346701e7d35SJeremy L Thompson     CeedInt num_points, num_comp;
1347701e7d35SJeremy L Thompson 
1348701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_u_len));
1349701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, elem, &num_points));
1350701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
1351701e7d35SJeremy L Thompson     min_ru_len = (CeedSize)num_points * (CeedSize)num_comp;
13523ac8f562SJeremy L Thompson   } else {
1353701e7d35SJeremy L Thompson     CeedInt num_points, num_comp;
1354701e7d35SJeremy L Thompson 
1355701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, elem, &num_points));
1356701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
1357701e7d35SJeremy L Thompson     min_u_len = (CeedSize)num_points * (CeedSize)num_comp;
1358701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_ru_len));
13593ac8f562SJeremy L Thompson   }
1360701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(u, &len));
13619bc66399SJeremy L Thompson   CeedCheck(min_u_len <= len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
13623ac8f562SJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT
13633ac8f562SJeremy L Thompson             ") for element %" CeedInt_FMT,
1364701e7d35SJeremy L Thompson             len, min_ru_len, min_u_len, elem);
1365701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(ru, &len));
13669bc66399SJeremy L Thompson   CeedCheck(min_ru_len <= len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
13673ac8f562SJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT
13683ac8f562SJeremy L Thompson             ") for element %" CeedInt_FMT,
1369701e7d35SJeremy L Thompson             len, min_ru_len, min_u_len, elem);
1370701e7d35SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
13719bc66399SJeremy L Thompson   CeedCheck(elem < num_elem, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
1372701e7d35SJeremy L Thompson             "Cannot retrieve element %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", elem, elem, num_elem);
1373701e7d35SJeremy L Thompson   if (num_elem > 0) CeedCall(rstr->ApplyAtPointsInElement(rstr, elem, t_mode, u, ru, request));
13743ac8f562SJeremy L Thompson   return CEED_ERROR_SUCCESS;
13753ac8f562SJeremy L Thompson }
13763ac8f562SJeremy L Thompson 
13773ac8f562SJeremy L Thompson /**
1378d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
1379be9261b7Sjeremylt 
1380ca94c3ddSJeremy L Thompson   @param[in]  rstr    `CeedElemRestriction`
1381ca94c3ddSJeremy 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]`
1382ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1383ca94c3ddSJeremy L Thompson   @param[in]  u       Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE)
1384ca94c3ddSJeremy L Thompson   @param[out] ru      Output vector (of shape `[block_size * elem_size]` when `t_mode` = @ref CEED_NOTRANSPOSE).
1385fcbe8c06SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
1386ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
1387be9261b7Sjeremylt 
1388be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
1389be9261b7Sjeremylt 
13907a982d89SJeremy L. Thompson   @ref Backend
1391be9261b7Sjeremylt **/
13922b730f8bSJeremy L Thompson int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
13932b730f8bSJeremy L Thompson                                   CeedRequest *request) {
1394701e7d35SJeremy L Thompson   CeedSize min_u_len, min_ru_len, len;
1395701e7d35SJeremy L Thompson   CeedInt  block_size, num_elem;
1396be9261b7Sjeremylt 
13979bc66399SJeremy L Thompson   CeedCheck(rstr->ApplyBlock, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED,
13989bc66399SJeremy L Thompson             "Backend does not implement CeedElemRestrictionApplyBlock");
13996402da51SJeremy L Thompson 
1400701e7d35SJeremy L Thompson   CeedCall(CeedElemRestrictionGetBlockSize(rstr, &block_size));
1401d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
1402701e7d35SJeremy L Thompson     CeedInt elem_size, num_comp;
1403701e7d35SJeremy L Thompson 
1404701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetElementSize(rstr, &elem_size));
1405701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
1406701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_u_len));
1407701e7d35SJeremy L Thompson     min_ru_len = (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1408be9261b7Sjeremylt   } else {
1409701e7d35SJeremy L Thompson     CeedInt elem_size, num_comp;
1410701e7d35SJeremy L Thompson 
1411701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetElementSize(rstr, &elem_size));
1412701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp));
1413701e7d35SJeremy L Thompson     CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_ru_len));
1414701e7d35SJeremy L Thompson     min_u_len = (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp;
1415be9261b7Sjeremylt   }
1416701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(u, &len));
14179bc66399SJeremy L Thompson   CeedCheck(min_u_len == len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
1418701e7d35SJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_u_len,
1419701e7d35SJeremy L Thompson             min_ru_len);
1420701e7d35SJeremy L Thompson   CeedCall(CeedVectorGetLength(ru, &len));
14219bc66399SJeremy L Thompson   CeedCheck(min_ru_len == len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
1422701e7d35SJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_ru_len,
1423701e7d35SJeremy L Thompson             min_u_len);
1424701e7d35SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
14259bc66399SJeremy L Thompson   CeedCheck(block_size * block <= num_elem, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION,
1426701e7d35SJeremy L Thompson             "Cannot retrieve block %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", block, block_size * block,
1427701e7d35SJeremy L Thompson             num_elem);
14282b730f8bSJeremy L Thompson   CeedCall(rstr->ApplyBlock(rstr, block, t_mode, u, ru, request));
1429e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1430be9261b7Sjeremylt }
1431be9261b7Sjeremylt 
1432be9261b7Sjeremylt /**
1433ca94c3ddSJeremy L Thompson   @brief Get the `Ceed` associated with a `CeedElemRestriction`
1434b7c9bbdaSJeremy L Thompson 
1435ca94c3ddSJeremy L Thompson   @param[in]  rstr `CeedElemRestriction`
1436ca94c3ddSJeremy L Thompson   @param[out] ceed Variable to store `Ceed`
1437b7c9bbdaSJeremy L Thompson 
1438b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1439b7c9bbdaSJeremy L Thompson 
1440b7c9bbdaSJeremy L Thompson   @ref Advanced
1441b7c9bbdaSJeremy L Thompson **/
1442b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
1443b0f67a9cSJeremy L Thompson   CeedCall(CeedObjectGetCeed((CeedObject)rstr, ceed));
1444b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1445b7c9bbdaSJeremy L Thompson }
1446b7c9bbdaSJeremy L Thompson 
1447b7c9bbdaSJeremy L Thompson /**
14486e536b99SJeremy L Thompson   @brief Return the `Ceed` associated with a `CeedElemRestriction`
14496e536b99SJeremy L Thompson 
14506e536b99SJeremy L Thompson   @param[in]  rstr `CeedElemRestriction`
14516e536b99SJeremy L Thompson 
14526e536b99SJeremy L Thompson   @return `Ceed` associated with the `rstr`
14536e536b99SJeremy L Thompson 
14546e536b99SJeremy L Thompson   @ref Advanced
14556e536b99SJeremy L Thompson **/
1456b0f67a9cSJeremy L Thompson Ceed CeedElemRestrictionReturnCeed(CeedElemRestriction rstr) { return CeedObjectReturnCeed((CeedObject)rstr); }
14576e536b99SJeremy L Thompson 
14586e536b99SJeremy L Thompson /**
1459d979a051Sjeremylt   @brief Get the L-vector component stride
1460a681ae63Sjeremylt 
1461ca94c3ddSJeremy L Thompson   @param[in]  rstr        `CeedElemRestriction`
1462d1d35e2fSjeremylt   @param[out] comp_stride Variable to store component stride
1463a681ae63Sjeremylt 
1464a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1465a681ae63Sjeremylt 
1466b7c9bbdaSJeremy L Thompson   @ref Advanced
1467a681ae63Sjeremylt **/
14682b730f8bSJeremy L Thompson int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, CeedInt *comp_stride) {
1469d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
1470e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1471a681ae63Sjeremylt }
1472a681ae63Sjeremylt 
1473a681ae63Sjeremylt /**
1474ca94c3ddSJeremy L Thompson   @brief Get the total number of elements in the range of a `CeedElemRestriction`
1475a681ae63Sjeremylt 
1476ca94c3ddSJeremy L Thompson   @param[in] rstr      `CeedElemRestriction`
1477d1d35e2fSjeremylt   @param[out] num_elem Variable to store number of elements
1478a681ae63Sjeremylt 
1479a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1480a681ae63Sjeremylt 
1481b7c9bbdaSJeremy L Thompson   @ref Advanced
1482a681ae63Sjeremylt **/
14832b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, CeedInt *num_elem) {
1484d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
1485e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1486a681ae63Sjeremylt }
1487a681ae63Sjeremylt 
1488a681ae63Sjeremylt /**
1489ca94c3ddSJeremy L Thompson   @brief Get the size of elements in the `CeedElemRestriction`
1490a681ae63Sjeremylt 
1491ca94c3ddSJeremy L Thompson   @param[in]  rstr      `CeedElemRestriction`
1492d1d35e2fSjeremylt   @param[out] elem_size Variable to store size of elements
1493a681ae63Sjeremylt 
1494a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1495a681ae63Sjeremylt 
1496b7c9bbdaSJeremy L Thompson   @ref Advanced
1497a681ae63Sjeremylt **/
14982b730f8bSJeremy L Thompson int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, CeedInt *elem_size) {
1499d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
15002c7e7413SJeremy L Thompson   return CEED_ERROR_SUCCESS;
15012c7e7413SJeremy L Thompson }
15022c7e7413SJeremy L Thompson 
15032c7e7413SJeremy L Thompson /**
150407d5dec1SJeremy L Thompson 
1505725a297dSZach Atkins   @brief Get the number of points in the offsets array for a points `CeedElemRestriction`
150607d5dec1SJeremy L Thompson 
1507ca94c3ddSJeremy L Thompson   @param[in]  rstr       `CeedElemRestriction`
1508725a297dSZach Atkins   @param[out] num_points The number of points in the offsets array
150907d5dec1SJeremy L Thompson 
151007d5dec1SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
151107d5dec1SJeremy L Thompson 
1512c63574e3SJeremy L Thompson   @ref User
151307d5dec1SJeremy L Thompson **/
151407d5dec1SJeremy L Thompson int CeedElemRestrictionGetNumPoints(CeedElemRestriction rstr, CeedInt *num_points) {
15151203703bSJeremy L Thompson   CeedRestrictionType rstr_type;
151607d5dec1SJeremy L Thompson 
15171203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
15186e536b99SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
151907d5dec1SJeremy L Thompson             "Can only retrieve the number of points for a points CeedElemRestriction");
152007d5dec1SJeremy L Thompson 
152107d5dec1SJeremy L Thompson   *num_points = rstr->num_points;
152207d5dec1SJeremy L Thompson   return CEED_ERROR_SUCCESS;
152307d5dec1SJeremy L Thompson }
152407d5dec1SJeremy L Thompson 
152507d5dec1SJeremy L Thompson /**
152607d5dec1SJeremy L Thompson 
1527ca94c3ddSJeremy L Thompson   @brief Get the number of points in an element of a `CeedElemRestriction` at points
152807d5dec1SJeremy L Thompson 
1529ca94c3ddSJeremy L Thompson   @param[in]  rstr       `CeedElemRestriction`
153007d5dec1SJeremy L Thompson   @param[in]  elem       Index number of element to retrieve the number of points for
153107d5dec1SJeremy L Thompson   @param[out] num_points The number of points in the element at index elem
153207d5dec1SJeremy L Thompson 
153307d5dec1SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
153407d5dec1SJeremy L Thompson 
1535c63574e3SJeremy L Thompson   @ref User
153607d5dec1SJeremy L Thompson **/
153707d5dec1SJeremy L Thompson int CeedElemRestrictionGetNumPointsInElement(CeedElemRestriction rstr, CeedInt elem, CeedInt *num_points) {
15381203703bSJeremy L Thompson   CeedRestrictionType rstr_type;
153907d5dec1SJeremy L Thompson   const CeedInt      *offsets;
154007d5dec1SJeremy L Thompson 
15411203703bSJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
15426e536b99SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
154307d5dec1SJeremy L Thompson             "Can only retrieve the number of points for a points CeedElemRestriction");
154407d5dec1SJeremy L Thompson 
154507d5dec1SJeremy L Thompson   CeedCall(CeedElemRestrictionGetOffsets(rstr, CEED_MEM_HOST, &offsets));
154607d5dec1SJeremy L Thompson   *num_points = offsets[elem + 1] - offsets[elem];
154707d5dec1SJeremy L Thompson   CeedCall(CeedElemRestrictionRestoreOffsets(rstr, &offsets));
154807d5dec1SJeremy L Thompson   return CEED_ERROR_SUCCESS;
154907d5dec1SJeremy L Thompson }
155007d5dec1SJeremy L Thompson 
155107d5dec1SJeremy L Thompson /**
1552a4065bfbSZach Atkins   @brief Get the minimum and/or maximum number of points in an element for a `CeedElemRestriction` at points
15532c7e7413SJeremy L Thompson 
1554ca94c3ddSJeremy L Thompson   @param[in]  rstr       `CeedElemRestriction`
1555a4065bfbSZach Atkins   @param[out] min_points Variable to minimum number of points in an element, or `NULL`
1556a4065bfbSZach Atkins   @param[out] max_points Variable to maximum number of points in an element, or `NULL`
15572c7e7413SJeremy L Thompson 
15582c7e7413SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
15592c7e7413SJeremy L Thompson 
15602c7e7413SJeremy L Thompson   @ref Advanced
15612c7e7413SJeremy L Thompson **/
1562a4065bfbSZach Atkins int CeedElemRestrictionGetMinMaxPointsInElement(CeedElemRestriction rstr, CeedInt *min_points, CeedInt *max_points) {
1563a4065bfbSZach Atkins   CeedInt             num_elem, num_points;
15642c7e7413SJeremy L Thompson   CeedRestrictionType rstr_type;
15652c7e7413SJeremy L Thompson 
15662c7e7413SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
15676e536b99SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE,
1568a4065bfbSZach Atkins             "Cannot compute min/max points for a CeedElemRestriction that does not use points");
15692c7e7413SJeremy L Thompson 
15702c7e7413SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
15712c7e7413SJeremy L Thompson 
1572a4065bfbSZach Atkins   // Exit early if there are no elements
1573a4065bfbSZach Atkins   if (num_elem == 0) {
1574a4065bfbSZach Atkins     if (min_points) *min_points = 0;
1575a4065bfbSZach Atkins     if (max_points) *max_points = 0;
1576a4065bfbSZach Atkins     return CEED_ERROR_SUCCESS;
1577a4065bfbSZach Atkins   }
1578a4065bfbSZach Atkins 
1579a4065bfbSZach Atkins   // Initialize to the number of points in the first element
1580a4065bfbSZach Atkins   CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, 0, &num_points));
1581a4065bfbSZach Atkins   if (min_points) *min_points = num_points;
1582a4065bfbSZach Atkins   if (max_points) *max_points = num_points;
1583a4065bfbSZach Atkins   for (CeedInt e = 1; e < num_elem; e++) {
15842c7e7413SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, e, &num_points));
1585a4065bfbSZach Atkins     if (min_points) *min_points = CeedIntMin(num_points, *min_points);
1586a4065bfbSZach Atkins     if (max_points) *max_points = CeedIntMax(num_points, *max_points);
15872c7e7413SJeremy L Thompson   }
1588e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1589a681ae63Sjeremylt }
1590a681ae63Sjeremylt 
1591a681ae63Sjeremylt /**
1592a4065bfbSZach Atkins   @brief Get the maximum number of points in an element for a `CeedElemRestriction` at points
1593a4065bfbSZach Atkins 
1594a4065bfbSZach Atkins   @param[in]  rstr       `CeedElemRestriction`
1595a4065bfbSZach Atkins   @param[out] max_points Variable to store maximum number of points in an element
1596a4065bfbSZach Atkins 
1597a4065bfbSZach Atkins   @return An error code: 0 - success, otherwise - failure
1598a4065bfbSZach Atkins 
1599a4065bfbSZach Atkins   @ref User
1600a4065bfbSZach Atkins 
1601a4065bfbSZach Atkins   @see CeedElemRestrictionGetMinMaxPointsInElement()
1602a4065bfbSZach Atkins **/
1603a4065bfbSZach Atkins int CeedElemRestrictionGetMaxPointsInElement(CeedElemRestriction rstr, CeedInt *max_points) {
1604a4065bfbSZach Atkins   return CeedElemRestrictionGetMinMaxPointsInElement(rstr, NULL, max_points);
1605a4065bfbSZach Atkins }
1606a4065bfbSZach Atkins 
1607a4065bfbSZach Atkins /**
1608a4065bfbSZach Atkins   @brief Get the minimum number of points in an element for a `CeedElemRestriction` at points
1609a4065bfbSZach Atkins 
1610a4065bfbSZach Atkins   @param[in]  rstr       `CeedElemRestriction`
1611a4065bfbSZach Atkins   @param[out] min_points Variable to store minimum number of points in an element
1612a4065bfbSZach Atkins 
1613a4065bfbSZach Atkins   @return An error code: 0 - success, otherwise - failure
1614a4065bfbSZach Atkins 
1615a4065bfbSZach Atkins   @ref User
1616a4065bfbSZach Atkins 
1617a4065bfbSZach Atkins   @see CeedElemRestrictionGetMinMaxPointsInElement()
1618a4065bfbSZach Atkins **/
1619a4065bfbSZach Atkins int CeedElemRestrictionGetMinPointsInElement(CeedElemRestriction rstr, CeedInt *min_points) {
1620a4065bfbSZach Atkins   return CeedElemRestrictionGetMinMaxPointsInElement(rstr, min_points, NULL);
1621a4065bfbSZach Atkins }
1622a4065bfbSZach Atkins 
1623a4065bfbSZach Atkins /**
1624ca94c3ddSJeremy L Thompson   @brief Get the size of the l-vector for a `CeedElemRestriction`
1625a681ae63Sjeremylt 
1626ca94c3ddSJeremy L Thompson   @param[in]  rstr   `CeedElemRestriction`
1627701e7d35SJeremy L Thompson   @param[out] l_size Variable to store l-vector size
1628a681ae63Sjeremylt 
1629a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1630a681ae63Sjeremylt 
1631b7c9bbdaSJeremy L Thompson   @ref Advanced
1632a681ae63Sjeremylt **/
16332b730f8bSJeremy L Thompson int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, CeedSize *l_size) {
1634d1d35e2fSjeremylt   *l_size = rstr->l_size;
1635e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1636a681ae63Sjeremylt }
1637a681ae63Sjeremylt 
1638a681ae63Sjeremylt /**
1639701e7d35SJeremy L Thompson   @brief Get the size of the e-vector for a `CeedElemRestriction`
1640701e7d35SJeremy L Thompson 
1641701e7d35SJeremy L Thompson   @param[in]  rstr   `CeedElemRestriction`
1642701e7d35SJeremy L Thompson   @param[out] e_size Variable to store e-vector size
1643701e7d35SJeremy L Thompson 
1644701e7d35SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1645701e7d35SJeremy L Thompson 
1646701e7d35SJeremy L Thompson   @ref Advanced
1647701e7d35SJeremy L Thompson **/
1648701e7d35SJeremy L Thompson int CeedElemRestrictionGetEVectorSize(CeedElemRestriction rstr, CeedSize *e_size) {
1649701e7d35SJeremy L Thompson   *e_size = rstr->e_size;
1650701e7d35SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1651701e7d35SJeremy L Thompson }
1652701e7d35SJeremy L Thompson 
1653701e7d35SJeremy L Thompson /**
1654ca94c3ddSJeremy L Thompson   @brief Get the number of components in the elements of a `CeedElemRestriction`
1655a681ae63Sjeremylt 
1656ca94c3ddSJeremy L Thompson   @param[in]  rstr     `CeedElemRestriction`
1657d1d35e2fSjeremylt   @param[out] num_comp Variable to store number of components
1658a681ae63Sjeremylt 
1659a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1660a681ae63Sjeremylt 
1661b7c9bbdaSJeremy L Thompson   @ref Advanced
1662a681ae63Sjeremylt **/
16632b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, CeedInt *num_comp) {
1664d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
1665e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1666a681ae63Sjeremylt }
1667a681ae63Sjeremylt 
1668a681ae63Sjeremylt /**
1669ca94c3ddSJeremy L Thompson   @brief Get the number of blocks in a `CeedElemRestriction`
1670a681ae63Sjeremylt 
1671ca94c3ddSJeremy L Thompson   @param[in]  rstr      `CeedElemRestriction`
1672d1d35e2fSjeremylt   @param[out] num_block Variable to store number of blocks
1673a681ae63Sjeremylt 
1674a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1675a681ae63Sjeremylt 
1676b7c9bbdaSJeremy L Thompson   @ref Advanced
1677a681ae63Sjeremylt **/
16782b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, CeedInt *num_block) {
1679e7f679fcSJeremy L Thompson   *num_block = rstr->num_block;
1680e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1681a681ae63Sjeremylt }
1682a681ae63Sjeremylt 
1683a681ae63Sjeremylt /**
1684ca94c3ddSJeremy L Thompson   @brief Get the size of blocks in the `CeedElemRestriction`
1685a681ae63Sjeremylt 
1686ca94c3ddSJeremy L Thompson   @param[in]  rstr       `CeedElemRestriction`
1687e7f679fcSJeremy L Thompson   @param[out] block_size Variable to store size of blocks
1688a681ae63Sjeremylt 
1689a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1690a681ae63Sjeremylt 
1691b7c9bbdaSJeremy L Thompson   @ref Advanced
1692a681ae63Sjeremylt **/
1693e7f679fcSJeremy L Thompson int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, CeedInt *block_size) {
1694e7f679fcSJeremy L Thompson   *block_size = rstr->block_size;
1695e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1696a681ae63Sjeremylt }
1697a681ae63Sjeremylt 
1698a681ae63Sjeremylt /**
1699ca94c3ddSJeremy L Thompson   @brief Get the multiplicity of nodes in a `CeedElemRestriction`
17001469ee4dSjeremylt 
1701ca94c3ddSJeremy L Thompson   @param[in]  rstr `CeedElemRestriction`
1702ca94c3ddSJeremy L Thompson   @param[out] mult Vector to store multiplicity (of size `l_size`)
17031469ee4dSjeremylt 
17041469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
17051469ee4dSjeremylt 
17067a982d89SJeremy L. Thompson   @ref User
17071469ee4dSjeremylt **/
17082b730f8bSJeremy L Thompson int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, CeedVector mult) {
1709d1d35e2fSjeremylt   CeedVector e_vec;
17101469ee4dSjeremylt 
171125509ebbSRezgar Shakeri   // Create e_vec to hold intermediate computation in E^T (E 1)
17122b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionCreateVector(rstr, NULL, &e_vec));
17131469ee4dSjeremylt 
171425509ebbSRezgar Shakeri   // Compute e_vec = E * 1
17152b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 1.0));
17162b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, CEED_REQUEST_IMMEDIATE));
171725509ebbSRezgar Shakeri   // Compute multiplicity, mult = E^T * e_vec = E^T (E 1)
17182b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 0.0));
17192b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, CEED_REQUEST_IMMEDIATE));
17201469ee4dSjeremylt   // Cleanup
17212b730f8bSJeremy L Thompson   CeedCall(CeedVectorDestroy(&e_vec));
1722e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
17231469ee4dSjeremylt }
17241469ee4dSjeremylt 
17251469ee4dSjeremylt /**
17264c789ea2SJeremy L Thompson   @brief Set the number of tabs to indent for @ref CeedElemRestrictionView() output
17274c789ea2SJeremy L Thompson 
17284c789ea2SJeremy L Thompson   @param[in] rstr     `CeedElemRestriction` to set the number of view tabs
17294c789ea2SJeremy L Thompson   @param[in] num_tabs Number of view tabs to set
17304c789ea2SJeremy L Thompson 
17314c789ea2SJeremy L Thompson   @return Error code: 0 - success, otherwise - failure
17324c789ea2SJeremy L Thompson 
17334c789ea2SJeremy L Thompson   @ref User
17344c789ea2SJeremy L Thompson **/
17354c789ea2SJeremy L Thompson int CeedElemRestrictionSetNumViewTabs(CeedElemRestriction rstr, CeedInt num_tabs) {
1736*a299a25bSJeremy L Thompson   CeedCall(CeedObjectSetNumViewTabs((CeedObject)rstr, num_tabs));
17374c789ea2SJeremy L Thompson   return CEED_ERROR_SUCCESS;
17384c789ea2SJeremy L Thompson }
17394c789ea2SJeremy L Thompson 
17404c789ea2SJeremy L Thompson /**
1741690992b2SZach Atkins   @brief Get the number of tabs to indent for @ref CeedElemRestrictionView() output
1742690992b2SZach Atkins 
1743690992b2SZach Atkins   @param[in]  rstr     `CeedElemRestriction` to get the number of view tabs
1744690992b2SZach Atkins   @param[out] num_tabs Number of view tabs
1745690992b2SZach Atkins 
1746690992b2SZach Atkins   @return Error code: 0 - success, otherwise - failure
1747690992b2SZach Atkins 
1748690992b2SZach Atkins   @ref User
1749690992b2SZach Atkins **/
1750690992b2SZach Atkins int CeedElemRestrictionGetNumViewTabs(CeedElemRestriction rstr, CeedInt *num_tabs) {
1751*a299a25bSJeremy L Thompson   CeedCall(CeedObjectGetNumViewTabs((CeedObject)rstr, num_tabs));
1752690992b2SZach Atkins   return CEED_ERROR_SUCCESS;
1753690992b2SZach Atkins }
1754690992b2SZach Atkins 
1755690992b2SZach Atkins /**
1756ca94c3ddSJeremy L Thompson   @brief View a `CeedElemRestriction`
1757f02ca4a2SJed Brown 
1758ca94c3ddSJeremy L Thompson   @param[in] rstr   `CeedElemRestriction` to view
1759ca94c3ddSJeremy L Thompson   @param[in] stream Stream to write; typically `stdout` or a file
1760f02ca4a2SJed Brown 
1761f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
1762f02ca4a2SJed Brown 
17637a982d89SJeremy L. Thompson   @ref User
1764f02ca4a2SJed Brown **/
1765f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
17664c789ea2SJeremy L Thompson   char               *tabs = NULL;
17670930e4e7SJeremy L Thompson   CeedRestrictionType rstr_type;
17680930e4e7SJeremy L Thompson 
17694c789ea2SJeremy L Thompson   {
17704c789ea2SJeremy L Thompson     CeedInt num_tabs = 0;
17714c789ea2SJeremy L Thompson 
17724c789ea2SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumViewTabs(rstr, &num_tabs));
17734c789ea2SJeremy L Thompson     CeedCall(CeedCalloc(CEED_TAB_WIDTH * num_tabs + 1, &tabs));
17744c789ea2SJeremy L Thompson     for (CeedInt i = 0; i < CEED_TAB_WIDTH * num_tabs; i++) tabs[i] = ' ';
17754c789ea2SJeremy L Thompson   }
17764c789ea2SJeremy L Thompson 
17770930e4e7SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
17780930e4e7SJeremy L Thompson   if (rstr_type == CEED_RESTRICTION_POINTS) {
17790930e4e7SJeremy L Thompson     CeedInt max_points;
17800930e4e7SJeremy L Thompson 
17810930e4e7SJeremy L Thompson     CeedCall(CeedElemRestrictionGetMaxPointsInElement(rstr, &max_points));
17820930e4e7SJeremy L Thompson     fprintf(stream,
17834c789ea2SJeremy L Thompson             "%sCeedElemRestriction at points from (%" CeedSize_FMT ", %" CeedInt_FMT ") to %" CeedInt_FMT " elements with a maximum of %" CeedInt_FMT
17840930e4e7SJeremy L Thompson             " points on an element\n",
17854c789ea2SJeremy L Thompson             tabs, rstr->l_size, rstr->num_comp, rstr->num_elem, max_points);
17860930e4e7SJeremy L Thompson   } else {
1787249f8407SJeremy L Thompson     char strides_str[500];
17881c66c397SJeremy L Thompson 
17892b730f8bSJeremy L Thompson     if (rstr->strides) {
1790249f8407SJeremy L Thompson       sprintf(strides_str, "[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "]", rstr->strides[0], rstr->strides[1], rstr->strides[2]);
17912b730f8bSJeremy L Thompson     } else {
1792249f8407SJeremy L Thompson       sprintf(strides_str, "%" CeedInt_FMT, rstr->comp_stride);
17932b730f8bSJeremy L Thompson     }
1794249f8407SJeremy L Thompson     fprintf(stream,
17954c789ea2SJeremy L Thompson             "%s%sCeedElemRestriction from (%" CeedSize_FMT ", %" CeedInt_FMT ") to %" CeedInt_FMT " elements with %" CeedInt_FMT
1796249f8407SJeremy L Thompson             " nodes each and %s %s\n",
17974c789ea2SJeremy L Thompson             tabs, rstr->block_size > 1 ? "Blocked " : "", rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
1798249f8407SJeremy L Thompson             rstr->strides ? "strides" : "component stride", strides_str);
17990930e4e7SJeremy L Thompson   }
18004c789ea2SJeremy L Thompson   CeedCall(CeedFree(&tabs));
1801e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1802f02ca4a2SJed Brown }
1803f02ca4a2SJed Brown 
1804f02ca4a2SJed Brown /**
1805ca94c3ddSJeremy L Thompson   @brief Destroy a `CeedElemRestriction`
1806b11c1e72Sjeremylt 
1807ca94c3ddSJeremy L Thompson   @param[in,out] rstr `CeedElemRestriction` to destroy
1808b11c1e72Sjeremylt 
1809b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1810dfdf5a53Sjeremylt 
18117a982d89SJeremy L. Thompson   @ref User
1812b11c1e72Sjeremylt **/
18134ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
1814b0f67a9cSJeremy L Thompson   if (!*rstr || *rstr == CEED_ELEMRESTRICTION_NONE || CeedObjectDereference((CeedObject)*rstr) > 0) {
1815ad6481ceSJeremy L Thompson     *rstr = NULL;
1816ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
1817ad6481ceSJeremy L Thompson   }
1818b0f67a9cSJeremy L Thompson   CeedCheck((*rstr)->num_readers == 0, CeedElemRestrictionReturnCeed(*rstr), CEED_ERROR_ACCESS,
18196574a04fSJeremy L Thompson             "Cannot destroy CeedElemRestriction, a process has read access to the offset data");
1820c17ec2beSJeremy L Thompson 
1821c17ec2beSJeremy L Thompson   // Only destroy backend data once between rstr and unsigned copy
18227c1dbaffSSebastian Grimberg   if ((*rstr)->rstr_base) CeedCall(CeedElemRestrictionDestroy(&(*rstr)->rstr_base));
1823c17ec2beSJeremy L Thompson   else if ((*rstr)->Destroy) CeedCall((*rstr)->Destroy(*rstr));
1824c17ec2beSJeremy L Thompson 
18252b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*rstr)->strides));
1826b0f67a9cSJeremy L Thompson   CeedCall(CeedObjectDestroy(&(*rstr)->obj));
18272b730f8bSJeremy L Thompson   CeedCall(CeedFree(rstr));
1828e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1829d7b241e6Sjeremylt }
1830d7b241e6Sjeremylt 
1831d7b241e6Sjeremylt /// @}
1832