xref: /libCEED/interface/ceed-elemrestriction.c (revision 48acf7109003d10be9ba6e2ea1703bbbf207ad3b)
13d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3d7b241e6Sjeremylt //
43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
5d7b241e6Sjeremylt //
63d8e8822SJeremy L Thompson // This file is part of CEED:  http://github.com/ceed
7d7b241e6Sjeremylt 
83d576824SJeremy L Thompson #include <ceed-impl.h>
949aac155SJeremy L Thompson #include <ceed.h>
102b730f8bSJeremy L Thompson #include <ceed/backend.h>
113d576824SJeremy L Thompson #include <stdbool.h>
123d576824SJeremy L Thompson #include <stdio.h>
13c17ec2beSJeremy L Thompson #include <string.h>
14d7b241e6Sjeremylt 
157a982d89SJeremy L. Thompson /// @file
167a982d89SJeremy L. Thompson /// Implementation of CeedElemRestriction interfaces
177a982d89SJeremy L. Thompson 
187a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
197a982d89SJeremy L. Thompson /// CeedElemRestriction Library Internal Functions
207a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
217a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionDeveloper
227a982d89SJeremy L. Thompson /// @{
237a982d89SJeremy L. Thompson 
247a982d89SJeremy L. Thompson /**
25d979a051Sjeremylt   @brief Permute and pad offsets for a blocked restriction
267a982d89SJeremy L. Thompson 
27fcbe8c06SSebastian Grimberg   @param[in]  offsets        Array of shape [@a num_elem, @a elem_size].
28e7f679fcSJeremy L Thompson   @param[out] block_offsets  Array of permuted and padded array values of shape [@a num_block, @a elem_size, @a 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 /**
5177d1c127SSebastian Grimberg   @brief Permute and pad orientations for a blocked restriction
5277d1c127SSebastian Grimberg 
53fcbe8c06SSebastian Grimberg   @param[in]  orients       Array of shape [@a num_elem, @a elem_size].
54e7f679fcSJeremy L Thompson   @param[out] block_orients Array of permuted and padded array values of shape [@a num_block, @a elem_size, @a 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 /**
760c73c039SSebastian Grimberg   @brief Permute and pad curl-conforming orientations for a blocked restriction
770c73c039SSebastian Grimberg 
780c73c039SSebastian Grimberg   @param[in]  curl_orients       Array of shape [@a num_elem, @a 3 * elem_size].
79e7f679fcSJeremy L Thompson   @param[out] block_curl_orients Array of permuted and padded array values of shape [@a num_block, @a elem_size, @a block_size].
80e7f679fcSJeremy L Thompson   @param[in]  num_block          Number of blocks
810c73c039SSebastian Grimberg   @param[in]  num_elem           Number of elements
82e7f679fcSJeremy L Thompson   @param[in]  block_size         Number of elements in a block
830c73c039SSebastian Grimberg   @param[in]  elem_size          Size of each element
840c73c039SSebastian Grimberg 
850c73c039SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
860c73c039SSebastian Grimberg 
870c73c039SSebastian Grimberg   @ref Utility
880c73c039SSebastian Grimberg **/
89e7f679fcSJeremy L Thompson int CeedPermutePadCurlOrients(const CeedInt8 *curl_orients, CeedInt8 *block_curl_orients, CeedInt num_block, CeedInt num_elem, CeedInt block_size,
900c73c039SSebastian Grimberg                               CeedInt elem_size) {
91e7f679fcSJeremy L Thompson   for (CeedInt e = 0; e < num_block * block_size; e += block_size) {
92e7f679fcSJeremy L Thompson     for (CeedInt j = 0; j < block_size; j++) {
930c73c039SSebastian Grimberg       for (CeedInt k = 0; k < elem_size; k++) {
94e7f679fcSJeremy L Thompson         block_curl_orients[e * elem_size + k * block_size + j] = curl_orients[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
950c73c039SSebastian Grimberg       }
960c73c039SSebastian Grimberg     }
970c73c039SSebastian Grimberg   }
980c73c039SSebastian Grimberg   return CEED_ERROR_SUCCESS;
990c73c039SSebastian Grimberg }
1000c73c039SSebastian Grimberg 
1017a982d89SJeremy L. Thompson /// @}
1027a982d89SJeremy L. Thompson 
1037a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1047a982d89SJeremy L. Thompson /// CeedElemRestriction Backend API
1057a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1067a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionBackend
1077a982d89SJeremy L. Thompson /// @{
1087a982d89SJeremy L. Thompson 
1097a982d89SJeremy L. Thompson /**
110fcbe8c06SSebastian Grimberg   @brief Get the type of a CeedElemRestriction
111a681ae63Sjeremylt 
112fcbe8c06SSebastian Grimberg   @param[in]  rstr      CeedElemRestriction
113fcbe8c06SSebastian Grimberg   @param[out] rstr_type Variable to store restriction type
114fcbe8c06SSebastian Grimberg 
115fcbe8c06SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
116fcbe8c06SSebastian Grimberg 
117fcbe8c06SSebastian Grimberg   @ref Backend
118fcbe8c06SSebastian Grimberg **/
119fcbe8c06SSebastian Grimberg int CeedElemRestrictionGetType(CeedElemRestriction rstr, CeedRestrictionType *rstr_type) {
120fcbe8c06SSebastian Grimberg   *rstr_type = rstr->rstr_type;
121fcbe8c06SSebastian Grimberg   return CEED_ERROR_SUCCESS;
122fcbe8c06SSebastian Grimberg }
123fcbe8c06SSebastian Grimberg 
124fcbe8c06SSebastian Grimberg /**
125fcbe8c06SSebastian Grimberg   @brief Get the strided status of a CeedElemRestriction
126fcbe8c06SSebastian Grimberg 
127fcbe8c06SSebastian Grimberg   @param[in]  rstr       CeedElemRestriction
128fcbe8c06SSebastian Grimberg   @param[out] is_strided Variable to store strided status, 1 if strided else 0
129fcbe8c06SSebastian Grimberg **/
130fcbe8c06SSebastian Grimberg int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) {
131fcbe8c06SSebastian Grimberg   *is_strided = (rstr->rstr_type == CEED_RESTRICTION_STRIDED);
132fcbe8c06SSebastian Grimberg   return CEED_ERROR_SUCCESS;
133fcbe8c06SSebastian Grimberg }
134fcbe8c06SSebastian Grimberg 
135fcbe8c06SSebastian Grimberg /**
1363ac8f562SJeremy L Thompson   @brief Get the points status of a CeedElemRestriction
1373ac8f562SJeremy L Thompson 
1383ac8f562SJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
1393ac8f562SJeremy L Thompson   @param[out] is_points Variable to store points status, 1 if points else 0
1403ac8f562SJeremy L Thompson **/
1413ac8f562SJeremy L Thompson int CeedElemRestrictionIsPoints(CeedElemRestriction rstr, bool *is_points) {
1423ac8f562SJeremy L Thompson   *is_points = (rstr->rstr_type == CEED_RESTRICTION_POINTS);
1433ac8f562SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1443ac8f562SJeremy L Thompson }
1453ac8f562SJeremy L Thompson 
1463ac8f562SJeremy L Thompson /**
147*48acf710SJeremy L Thompson   @brief Check if two CeedElemRestrictionAtPoints use the same points per element
148*48acf710SJeremy L Thompson 
149*48acf710SJeremy L Thompson   @param[in]  rstr_a         First CeedElemRestriction
150*48acf710SJeremy L Thompson   @param[in]  rstr_b         Second CeedElemRestriction
151*48acf710SJeremy L Thompson   @param[out] are_compatible Variable to store compatibility status
152*48acf710SJeremy L Thompson **/
153*48acf710SJeremy L Thompson int CeedElemRestrictionAtPointsAreCompatible(CeedElemRestriction rstr_a, CeedElemRestriction rstr_b, bool *are_compatible) {
154*48acf710SJeremy L Thompson   CeedInt num_elem_a, num_elem_b, num_points_a, num_points_b;
155*48acf710SJeremy L Thompson 
156*48acf710SJeremy L Thompson   // Cannot compare non-points restrictions
157*48acf710SJeremy L Thompson   CeedCheck(rstr_a->rstr_type == CEED_RESTRICTION_POINTS, rstr_a->ceed, CEED_ERROR_UNSUPPORTED, "First ElemRestriction must be AtPoints");
158*48acf710SJeremy L Thompson   CeedCheck(rstr_b->rstr_type == CEED_RESTRICTION_POINTS, rstr_b->ceed, CEED_ERROR_UNSUPPORTED, "Second ElemRestriction must be AtPoints");
159*48acf710SJeremy L Thompson 
160*48acf710SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr_a, &num_elem_a));
161*48acf710SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr_b, &num_elem_b));
162*48acf710SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumPoints(rstr_a, &num_points_a));
163*48acf710SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumPoints(rstr_b, &num_points_b));
164*48acf710SJeremy L Thompson 
165*48acf710SJeremy L Thompson   // Check size and contents of offsets arrays
166*48acf710SJeremy L Thompson   *are_compatible = true;
167*48acf710SJeremy L Thompson   if (num_elem_a != num_elem_b) *are_compatible = false;
168*48acf710SJeremy L Thompson   if (num_points_a != num_points_b) *are_compatible = false;
169*48acf710SJeremy L Thompson   if (*are_compatible) {
170*48acf710SJeremy L Thompson     const CeedInt *offsets_a, *offsets_b;
171*48acf710SJeremy L Thompson 
172*48acf710SJeremy L Thompson     CeedCall(CeedElemRestrictionGetOffsets(rstr_a, CEED_MEM_HOST, &offsets_a));
173*48acf710SJeremy L Thompson     CeedCall(CeedElemRestrictionGetOffsets(rstr_b, CEED_MEM_HOST, &offsets_b));
174*48acf710SJeremy L Thompson     for (CeedInt i = 0; i < num_elem_a + 1 + num_points_a; i++) *are_compatible &= offsets_a[i] == offsets_b[i];
175*48acf710SJeremy L Thompson     CeedCall(CeedElemRestrictionRestoreOffsets(rstr_a, &offsets_a));
176*48acf710SJeremy L Thompson     CeedCall(CeedElemRestrictionRestoreOffsets(rstr_b, &offsets_b));
177*48acf710SJeremy L Thompson   }
178*48acf710SJeremy L Thompson   return CEED_ERROR_SUCCESS;
179*48acf710SJeremy L Thompson }
180*48acf710SJeremy L Thompson 
181*48acf710SJeremy L Thompson /**
182a681ae63Sjeremylt   @brief Get the strides of a strided CeedElemRestriction
1837a982d89SJeremy L. Thompson 
184ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
185a681ae63Sjeremylt   @param[out] strides Variable to store strides array
1867a982d89SJeremy L. Thompson 
1877a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1887a982d89SJeremy L. Thompson 
1897a982d89SJeremy L. Thompson   @ref Backend
1907a982d89SJeremy L. Thompson **/
1912b730f8bSJeremy L Thompson int CeedElemRestrictionGetStrides(CeedElemRestriction rstr, CeedInt (*strides)[3]) {
1926574a04fSJeremy L Thompson   CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
1932b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*strides)[i] = rstr->strides[i];
194e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1957a982d89SJeremy L. Thompson }
1967a982d89SJeremy L. Thompson 
1977a982d89SJeremy L. Thompson /**
19877d1c127SSebastian Grimberg   @brief Get the backend stride status of a CeedElemRestriction
19977d1c127SSebastian Grimberg 
20077d1c127SSebastian Grimberg   @param[in]  rstr                 CeedElemRestriction
20177d1c127SSebastian Grimberg   @param[out] has_backend_strides  Variable to store stride status
20277d1c127SSebastian Grimberg 
20377d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
20477d1c127SSebastian Grimberg 
20577d1c127SSebastian Grimberg   @ref Backend
20677d1c127SSebastian Grimberg **/
20777d1c127SSebastian Grimberg int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, bool *has_backend_strides) {
20877d1c127SSebastian Grimberg   CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
20977d1c127SSebastian Grimberg   *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
21077d1c127SSebastian Grimberg                           (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
21177d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
21277d1c127SSebastian Grimberg }
21377d1c127SSebastian Grimberg 
21477d1c127SSebastian Grimberg /**
215bd33150aSjeremylt   @brief Get read-only access to a CeedElemRestriction offsets array by memtype
216bd33150aSjeremylt 
217ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction to retrieve offsets
218fcbe8c06SSebastian Grimberg   @param[in]  mem_type Memory type on which to access the array.
219fcbe8c06SSebastian Grimberg                          If the backend uses a different memory type, this will perform a copy (possibly cached).
220d1d35e2fSjeremylt   @param[out] offsets  Array on memory type mem_type
221bd33150aSjeremylt 
222bd33150aSjeremylt   @return An error code: 0 - success, otherwise - failure
223bd33150aSjeremylt 
224bd33150aSjeremylt   @ref User
225bd33150aSjeremylt **/
2262b730f8bSJeremy L Thompson int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) {
2277c1dbaffSSebastian Grimberg   if (rstr->rstr_base) {
2287c1dbaffSSebastian Grimberg     CeedCall(CeedElemRestrictionGetOffsets(rstr->rstr_base, mem_type, offsets));
229c17ec2beSJeremy L Thompson   } else {
2306574a04fSJeremy L Thompson     CeedCheck(rstr->GetOffsets, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetOffsets");
2312b730f8bSJeremy L Thompson     CeedCall(rstr->GetOffsets(rstr, mem_type, offsets));
232d1d35e2fSjeremylt     rstr->num_readers++;
233c17ec2beSJeremy L Thompson   }
234e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
235430758c8SJeremy L Thompson }
236430758c8SJeremy L Thompson 
237430758c8SJeremy L Thompson /**
238430758c8SJeremy L Thompson   @brief Restore an offsets array obtained using CeedElemRestrictionGetOffsets()
239430758c8SJeremy L Thompson 
240ea61e9acSJeremy L Thompson   @param[in] rstr    CeedElemRestriction to restore
241ea61e9acSJeremy L Thompson   @param[in] offsets Array of offset data
242430758c8SJeremy L Thompson 
243430758c8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
244430758c8SJeremy L Thompson 
245430758c8SJeremy L Thompson   @ref User
246430758c8SJeremy L Thompson **/
2472b730f8bSJeremy L Thompson int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr, const CeedInt **offsets) {
2487c1dbaffSSebastian Grimberg   if (rstr->rstr_base) {
2497c1dbaffSSebastian Grimberg     CeedCall(CeedElemRestrictionRestoreOffsets(rstr->rstr_base, offsets));
250c17ec2beSJeremy L Thompson   } else {
251430758c8SJeremy L Thompson     *offsets = NULL;
252d1d35e2fSjeremylt     rstr->num_readers--;
253c17ec2beSJeremy L Thompson   }
254e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
255bd33150aSjeremylt }
256bd33150aSjeremylt 
257bd33150aSjeremylt /**
25877d1c127SSebastian Grimberg   @brief Get read-only access to a CeedElemRestriction orientations array by memtype
2593ac43b2cSJeremy L Thompson 
26077d1c127SSebastian Grimberg   @param[in]  rstr     CeedElemRestriction to retrieve orientations
261fcbe8c06SSebastian Grimberg   @param[in]  mem_type Memory type on which to access the array.
262fcbe8c06SSebastian Grimberg                          If the backend uses a different memory type, this will perform a copy (possibly cached).
26377d1c127SSebastian Grimberg   @param[out] orients  Array on memory type mem_type
2643ac43b2cSJeremy L Thompson 
2653ac43b2cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2663ac43b2cSJeremy L Thompson 
26777d1c127SSebastian Grimberg   @ref User
2683ac43b2cSJeremy L Thompson **/
26977d1c127SSebastian Grimberg int CeedElemRestrictionGetOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const bool **orients) {
270fcbe8c06SSebastian Grimberg   CeedCheck(rstr->GetOrientations, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetOrientations");
27177d1c127SSebastian Grimberg   CeedCall(rstr->GetOrientations(rstr, mem_type, orients));
27277d1c127SSebastian Grimberg   rstr->num_readers++;
273e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2743ac43b2cSJeremy L Thompson }
2753ac43b2cSJeremy L Thompson 
2763ac43b2cSJeremy L Thompson /**
27777d1c127SSebastian Grimberg   @brief Restore an orientations array obtained using CeedElemRestrictionGetOrientations()
278b435c5a6Srezgarshakeri 
27977d1c127SSebastian Grimberg   @param[in] rstr    CeedElemRestriction to restore
28077d1c127SSebastian Grimberg   @param[in] orients Array of orientation data
281b435c5a6Srezgarshakeri 
282b435c5a6Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
283b435c5a6Srezgarshakeri 
28477d1c127SSebastian Grimberg   @ref User
285b435c5a6Srezgarshakeri **/
28677d1c127SSebastian Grimberg int CeedElemRestrictionRestoreOrientations(CeedElemRestriction rstr, const bool **orients) {
28777d1c127SSebastian Grimberg   *orients = NULL;
28877d1c127SSebastian Grimberg   rstr->num_readers--;
289b435c5a6Srezgarshakeri   return CEED_ERROR_SUCCESS;
290b435c5a6Srezgarshakeri }
291b435c5a6Srezgarshakeri 
292b435c5a6Srezgarshakeri /**
29377d1c127SSebastian Grimberg   @brief Get read-only access to a CeedElemRestriction curl-conforming orientations array by memtype
2947a982d89SJeremy L. Thompson 
29577d1c127SSebastian Grimberg   @param[in]  rstr         CeedElemRestriction to retrieve curl-conforming orientations
296fcbe8c06SSebastian Grimberg   @param[in]  mem_type     Memory type on which to access the array.
297fcbe8c06SSebastian Grimberg                              If the backend uses a different memory type, this will perform a copy (possibly cached).
29877d1c127SSebastian Grimberg   @param[out] curl_orients Array on memory type mem_type
2997a982d89SJeremy L. Thompson 
3007a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3017a982d89SJeremy L. Thompson 
30277d1c127SSebastian Grimberg   @ref User
3037a982d89SJeremy L. Thompson **/
3040c73c039SSebastian Grimberg int CeedElemRestrictionGetCurlOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt8 **curl_orients) {
305fcbe8c06SSebastian Grimberg   CeedCheck(rstr->GetCurlOrientations, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetCurlOrientations");
30677d1c127SSebastian Grimberg   CeedCall(rstr->GetCurlOrientations(rstr, mem_type, curl_orients));
30777d1c127SSebastian Grimberg   rstr->num_readers++;
30877d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
30977d1c127SSebastian Grimberg }
31077d1c127SSebastian Grimberg 
31177d1c127SSebastian Grimberg /**
31277d1c127SSebastian Grimberg   @brief Restore an orientations array obtained using CeedElemRestrictionGetCurlOrientations()
31377d1c127SSebastian Grimberg 
31477d1c127SSebastian Grimberg   @param[in] rstr         CeedElemRestriction to restore
31577d1c127SSebastian Grimberg   @param[in] curl_orients Array of orientation data
31677d1c127SSebastian Grimberg 
31777d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
31877d1c127SSebastian Grimberg 
31977d1c127SSebastian Grimberg   @ref User
32077d1c127SSebastian Grimberg **/
3210c73c039SSebastian Grimberg int CeedElemRestrictionRestoreCurlOrientations(CeedElemRestriction rstr, const CeedInt8 **curl_orients) {
32277d1c127SSebastian Grimberg   *curl_orients = NULL;
32377d1c127SSebastian Grimberg   rstr->num_readers--;
324e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3257a982d89SJeremy L. Thompson }
3267a982d89SJeremy L. Thompson 
3277a982d89SJeremy L. Thompson /**
32849fd234cSJeremy L Thompson 
32949fd234cSJeremy L Thompson   @brief Get the E-vector layout of a CeedElemRestriction
33049fd234cSJeremy L Thompson 
331ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
332fcbe8c06SSebastian Grimberg   @param[out] layout  Variable to store layout array, stored as [nodes, components, elements].
333fcbe8c06SSebastian Grimberg                         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]
33449fd234cSJeremy L Thompson 
33549fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
33649fd234cSJeremy L Thompson 
33749fd234cSJeremy L Thompson   @ref Backend
33849fd234cSJeremy L Thompson **/
3392b730f8bSJeremy L Thompson int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, CeedInt (*layout)[3]) {
3406574a04fSJeremy L Thompson   CeedCheck(rstr->layout[0], rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no layout data");
3412b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*layout)[i] = rstr->layout[i];
342e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
34349fd234cSJeremy L Thompson }
34449fd234cSJeremy L Thompson 
34549fd234cSJeremy L Thompson /**
34649fd234cSJeremy L Thompson 
34749fd234cSJeremy L Thompson   @brief Set the E-vector layout of a CeedElemRestriction
34849fd234cSJeremy L Thompson 
349ea61e9acSJeremy L Thompson   @param[in] rstr   CeedElemRestriction
350ea61e9acSJeremy L Thompson   @param[in] layout Variable to containing layout array, stored as [nodes, components, elements].
351ea61e9acSJeremy 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]
35249fd234cSJeremy L Thompson 
35349fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
35449fd234cSJeremy L Thompson 
35549fd234cSJeremy L Thompson   @ref Backend
35649fd234cSJeremy L Thompson **/
3572b730f8bSJeremy L Thompson int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
3582b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) rstr->layout[i] = layout[i];
359e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
36049fd234cSJeremy L Thompson }
36149fd234cSJeremy L Thompson 
36249fd234cSJeremy L Thompson /**
3637a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedElemRestriction
3647a982d89SJeremy L. Thompson 
365ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
3667a982d89SJeremy L. Thompson   @param[out] data Variable to store data
3677a982d89SJeremy L. Thompson 
3687a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3697a982d89SJeremy L. Thompson 
3707a982d89SJeremy L. Thompson   @ref Backend
3717a982d89SJeremy L. Thompson **/
372777ff853SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) {
373777ff853SJeremy L Thompson   *(void **)data = rstr->data;
374e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3757a982d89SJeremy L. Thompson }
3767a982d89SJeremy L. Thompson 
3777a982d89SJeremy L. Thompson /**
3787a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedElemRestriction
3797a982d89SJeremy L. Thompson 
380ea61e9acSJeremy L Thompson   @param[in,out] rstr CeedElemRestriction
381ea61e9acSJeremy L Thompson   @param[in]     data Data to set
3827a982d89SJeremy L. Thompson 
3837a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3847a982d89SJeremy L. Thompson 
3857a982d89SJeremy L. Thompson   @ref Backend
3867a982d89SJeremy L. Thompson **/
387777ff853SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) {
388777ff853SJeremy L Thompson   rstr->data = data;
389e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3907a982d89SJeremy L. Thompson }
3917a982d89SJeremy L. Thompson 
39234359f16Sjeremylt /**
39334359f16Sjeremylt   @brief Increment the reference counter for a CeedElemRestriction
39434359f16Sjeremylt 
395ea61e9acSJeremy L Thompson   @param[in,out] rstr ElemRestriction to increment the reference counter
39634359f16Sjeremylt 
39734359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
39834359f16Sjeremylt 
39934359f16Sjeremylt   @ref Backend
40034359f16Sjeremylt **/
4019560d06aSjeremylt int CeedElemRestrictionReference(CeedElemRestriction rstr) {
40234359f16Sjeremylt   rstr->ref_count++;
40334359f16Sjeremylt   return CEED_ERROR_SUCCESS;
40434359f16Sjeremylt }
40534359f16Sjeremylt 
4066e15d496SJeremy L Thompson /**
4076e15d496SJeremy L Thompson   @brief Estimate number of FLOPs required to apply CeedElemRestriction in t_mode
4086e15d496SJeremy L Thompson 
409ea61e9acSJeremy L Thompson   @param[in]  rstr   ElemRestriction to estimate FLOPs for
410ea61e9acSJeremy L Thompson   @param[in]  t_mode Apply restriction or transpose
411ea61e9acSJeremy L Thompson   @param[out] flops  Address of variable to hold FLOPs estimate
4126e15d496SJeremy L Thompson 
4136e15d496SJeremy L Thompson   @ref Backend
4146e15d496SJeremy L Thompson **/
4152b730f8bSJeremy L Thompson int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedSize *flops) {
416e7f679fcSJeremy L Thompson   CeedInt             e_size = rstr->num_block * rstr->block_size * rstr->elem_size * rstr->num_comp, scale = 0;
41789edb9e3SSebastian Grimberg   CeedRestrictionType rstr_type;
4181c66c397SJeremy L Thompson 
41989edb9e3SSebastian Grimberg   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
4203ac8f562SJeremy L Thompson   if (rstr_type == CEED_RESTRICTION_POINTS) e_size = rstr->num_points * rstr->num_comp;
42177d1c127SSebastian Grimberg   if (t_mode == CEED_TRANSPOSE) {
42289edb9e3SSebastian Grimberg     switch (rstr_type) {
4233ac8f562SJeremy L Thompson       case CEED_RESTRICTION_POINTS:
4243ac8f562SJeremy L Thompson         scale = 0;
4253ac8f562SJeremy L Thompson         break;
42689edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STRIDED:
42789edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STANDARD:
42877d1c127SSebastian Grimberg         scale = 1;
42989edb9e3SSebastian Grimberg         break;
43089edb9e3SSebastian Grimberg       case CEED_RESTRICTION_ORIENTED:
43177d1c127SSebastian Grimberg         scale = 2;
43289edb9e3SSebastian Grimberg         break;
43389edb9e3SSebastian Grimberg       case CEED_RESTRICTION_CURL_ORIENTED:
43477d1c127SSebastian Grimberg         scale = 6;
43589edb9e3SSebastian Grimberg         break;
4366e15d496SJeremy L Thompson     }
43777d1c127SSebastian Grimberg   } else {
43889edb9e3SSebastian Grimberg     switch (rstr_type) {
43989edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STRIDED:
44089edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STANDARD:
4413ac8f562SJeremy L Thompson       case CEED_RESTRICTION_POINTS:
44277d1c127SSebastian Grimberg         scale = 0;
44389edb9e3SSebastian Grimberg         break;
44489edb9e3SSebastian Grimberg       case CEED_RESTRICTION_ORIENTED:
44577d1c127SSebastian Grimberg         scale = 1;
44689edb9e3SSebastian Grimberg         break;
44789edb9e3SSebastian Grimberg       case CEED_RESTRICTION_CURL_ORIENTED:
44877d1c127SSebastian Grimberg         scale = 5;
44989edb9e3SSebastian Grimberg         break;
45077d1c127SSebastian Grimberg     }
45177d1c127SSebastian Grimberg   }
4526e15d496SJeremy L Thompson   *flops = e_size * scale;
4536e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4546e15d496SJeremy L Thompson }
4556e15d496SJeremy L Thompson 
4567a982d89SJeremy L. Thompson /// @}
4577a982d89SJeremy L. Thompson 
45815910d16Sjeremylt /// @cond DOXYGEN_SKIP
45915910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
46015910d16Sjeremylt /// @endcond
46115910d16Sjeremylt 
4627a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
4637a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
4647a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
4657a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
466d7b241e6Sjeremylt /// @{
467d7b241e6Sjeremylt 
4687a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
46945f1e315Sjeremylt const CeedInt CEED_STRIDES_BACKEND[3] = {0};
4707a982d89SJeremy L. Thompson 
471356036faSJeremy L Thompson /// Argument for CeedOperatorSetField indicating that the field does not requre a CeedElemRestriction
4722b730f8bSJeremy L Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = &ceed_elemrestriction_none;
4737a982d89SJeremy L. Thompson 
474d7b241e6Sjeremylt /**
475b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
476d7b241e6Sjeremylt 
477ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
478ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array
479ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
480ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
481fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
482fcbe8c06SSebastian Grimberg                             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.
483fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
484fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
485ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
486ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
487fcbe8c06SSebastian Grimberg   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
488fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
489fcbe8c06SSebastian Grimberg 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
490ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
491d7b241e6Sjeremylt 
492b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
493dfdf5a53Sjeremylt 
4947a982d89SJeremy L. Thompson   @ref User
495b11c1e72Sjeremylt **/
4962b730f8bSJeremy L Thompson int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
4972b730f8bSJeremy L Thompson                               CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
4985fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
4995fe0d4faSjeremylt     Ceed delegate;
5006574a04fSJeremy L Thompson 
5012b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
50277d1c127SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
5032b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
504e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
5055fe0d4faSjeremylt   }
5065fe0d4faSjeremylt 
507e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
5086574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
5096574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
5106574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
511e022e1f8SJeremy L Thompson 
5122b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
513db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
514d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
515d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
516d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
517d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
518d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
519d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
52005fa913cSJeremy L Thompson   (*rstr)->e_size      = num_elem * elem_size * num_comp;
521e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
522e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
52361a27d74SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_STANDARD;
524fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, NULL, *rstr));
525e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
526d7b241e6Sjeremylt }
527d7b241e6Sjeremylt 
528d7b241e6Sjeremylt /**
52977d1c127SSebastian Grimberg   @brief Create a CeedElemRestriction with orientation signs
530fc0567d9Srezgarshakeri 
531ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
532ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array
533ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
534ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
535fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
536fcbe8c06SSebastian Grimberg                             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.
537fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
538fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
539ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
540ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
541fcbe8c06SSebastian Grimberg   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
542fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
543fcbe8c06SSebastian Grimberg 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
54477d1c127SSebastian Grimberg   @param[in]  orients     Array of shape [@a num_elem, @a elem_size] with bool false for positively oriented and true to flip the orientation.
545ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
546fc0567d9Srezgarshakeri 
547fc0567d9Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
548fc0567d9Srezgarshakeri 
549fc0567d9Srezgarshakeri   @ref User
550fc0567d9Srezgarshakeri **/
5512b730f8bSJeremy L Thompson int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
55277d1c127SSebastian Grimberg                                       CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orients,
553fc0567d9Srezgarshakeri                                       CeedElemRestriction *rstr) {
554fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreate) {
555fc0567d9Srezgarshakeri     Ceed delegate;
5566574a04fSJeremy L Thompson 
5572b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
558fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
5592b730f8bSJeremy L Thompson     CeedCall(
56077d1c127SSebastian Grimberg         CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, orients, rstr));
561fc0567d9Srezgarshakeri     return CEED_ERROR_SUCCESS;
562fc0567d9Srezgarshakeri   }
563fc0567d9Srezgarshakeri 
564e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
5656574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
5666574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
5676574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
568e022e1f8SJeremy L Thompson 
5692b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
570db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
571fc0567d9Srezgarshakeri   (*rstr)->ref_count   = 1;
572fc0567d9Srezgarshakeri   (*rstr)->num_elem    = num_elem;
573fc0567d9Srezgarshakeri   (*rstr)->elem_size   = elem_size;
574fc0567d9Srezgarshakeri   (*rstr)->num_comp    = num_comp;
575fc0567d9Srezgarshakeri   (*rstr)->comp_stride = comp_stride;
576fc0567d9Srezgarshakeri   (*rstr)->l_size      = l_size;
57705fa913cSJeremy L Thompson   (*rstr)->e_size      = num_elem * elem_size * num_comp;
578e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
579e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
580fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_ORIENTED;
581fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, orients, NULL, *rstr));
58277d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
58377d1c127SSebastian Grimberg }
58477d1c127SSebastian Grimberg 
58577d1c127SSebastian Grimberg /**
58677d1c127SSebastian Grimberg   @brief Create a CeedElemRestriction with a general tridiagonal transformation matrix for curl-conforming elements
58777d1c127SSebastian Grimberg 
58877d1c127SSebastian Grimberg   @param[in]  ceed         Ceed object where the CeedElemRestriction will be created
58977d1c127SSebastian Grimberg   @param[in]  num_elem     Number of elements described in the @a offsets array
59077d1c127SSebastian Grimberg   @param[in]  elem_size    Size (number of "nodes") per element
59177d1c127SSebastian Grimberg   @param[in]  num_comp     Number of field components per interpolation node (1 for scalar fields)
592fcbe8c06SSebastian Grimberg   @param[in]  comp_stride  Stride between components for the same L-vector "node".
593fcbe8c06SSebastian Grimberg                              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.
594fcbe8c06SSebastian Grimberg   @param[in]  l_size       The size of the L-vector.
595fcbe8c06SSebastian Grimberg                              This vector may be larger than the elements and fields given by this restriction.
59677d1c127SSebastian Grimberg   @param[in]  mem_type     Memory type of the @a offsets array, see CeedMemType
59777d1c127SSebastian Grimberg   @param[in]  copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
598fcbe8c06SSebastian Grimberg   @param[in]  offsets      Array of shape [@a num_elem, @a elem_size].
599fcbe8c06SSebastian Grimberg                              Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i,
600fcbe8c06SSebastian Grimberg where 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
6017c1dbaffSSebastian Grimberg   @param[in]  curl_orients Array of shape [@a num_elem, @a 3 * elem_size] representing a row-major tridiagonal matrix (curl_orients[i * 3 * elem_size]
6027c1dbaffSSebastian Grimberg = curl_orients[(i + 1) * 3 * elem_size - 1] = 0, where 0 <= i < @a num_elem) which is applied to the element unknowns upon restriction. This
6037c1dbaffSSebastian Grimberg orientation matrix allows for pairs of face degrees of freedom on elements for H(curl) spaces to be coupled in the element restriction operation,
6047c1dbaffSSebastian Grimberg which is a way to resolve face orientation issues for 3D meshes (https://dl.acm.org/doi/pdf/10.1145/3524456).
60577d1c127SSebastian Grimberg   @param[out] rstr         Address of the variable where the newly created CeedElemRestriction will be stored
60677d1c127SSebastian Grimberg 
60777d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
60877d1c127SSebastian Grimberg 
60977d1c127SSebastian Grimberg   @ref User
61077d1c127SSebastian Grimberg **/
61177d1c127SSebastian Grimberg int CeedElemRestrictionCreateCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
6120c73c039SSebastian Grimberg                                           CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const CeedInt8 *curl_orients,
61377d1c127SSebastian Grimberg                                           CeedElemRestriction *rstr) {
614fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreate) {
61577d1c127SSebastian Grimberg     Ceed delegate;
61677d1c127SSebastian Grimberg 
61777d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
618fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
61977d1c127SSebastian Grimberg     CeedCall(CeedElemRestrictionCreateCurlOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
62077d1c127SSebastian Grimberg                                                    curl_orients, rstr));
62177d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
62277d1c127SSebastian Grimberg   }
62377d1c127SSebastian Grimberg 
624e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
62577d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
62677d1c127SSebastian Grimberg   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
62777d1c127SSebastian Grimberg   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
62877d1c127SSebastian Grimberg 
62977d1c127SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
630fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
63177d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
63277d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
63377d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
63477d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
63577d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
63677d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
63705fa913cSJeremy L Thompson   (*rstr)->e_size      = num_elem * elem_size * num_comp;
638e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
639e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
640fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_CURL_ORIENTED;
641fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, curl_orients, *rstr));
642fc0567d9Srezgarshakeri   return CEED_ERROR_SUCCESS;
643fc0567d9Srezgarshakeri }
644fc0567d9Srezgarshakeri 
645fc0567d9Srezgarshakeri /**
6467509a596Sjeremylt   @brief Create a strided CeedElemRestriction
647d7b241e6Sjeremylt 
648ea61e9acSJeremy L Thompson   @param[in]  ceed      Ceed object where the CeedElemRestriction will be created
649ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
650ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
651ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation "node" (1 for scalar fields)
652fcbe8c06SSebastian Grimberg   @param[in]  l_size    The size of the L-vector.
653fcbe8c06SSebastian Grimberg                           This vector may be larger than the elements and fields given by this restriction.
654fcbe8c06SSebastian Grimberg   @param[in]  strides   Array for strides between [nodes, components, elements].
655fcbe8c06SSebastian Grimberg                           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].
656fcbe8c06SSebastian Grimberg                           @a CEED_STRIDES_BACKEND may be used with vectors created by a Ceed backend.
657ea61e9acSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created CeedElemRestriction will be stored
658d7b241e6Sjeremylt 
659b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
660dfdf5a53Sjeremylt 
6617a982d89SJeremy L. Thompson   @ref User
662b11c1e72Sjeremylt **/
6632b730f8bSJeremy L Thompson int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedSize l_size, const CeedInt strides[3],
664f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
6655fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
6665fe0d4faSjeremylt     Ceed delegate;
667b04eb3d9SSebastian Grimberg 
6682b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
669fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
6702b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, l_size, strides, rstr));
671e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6725fe0d4faSjeremylt   }
6735fe0d4faSjeremylt 
674e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
6756574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
6766574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
677e7f679fcSJeremy L Thompson   CeedCheck(l_size >= num_elem * elem_size * num_comp, ceed, CEED_ERROR_DIMENSION, "L-vector size must be at least num_elem * elem_size * num_comp");
678e022e1f8SJeremy L Thompson 
6792b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
680db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
681d1d35e2fSjeremylt   (*rstr)->ref_count  = 1;
682d1d35e2fSjeremylt   (*rstr)->num_elem   = num_elem;
683d1d35e2fSjeremylt   (*rstr)->elem_size  = elem_size;
684d1d35e2fSjeremylt   (*rstr)->num_comp   = num_comp;
685d1d35e2fSjeremylt   (*rstr)->l_size     = l_size;
68605fa913cSJeremy L Thompson   (*rstr)->e_size     = num_elem * elem_size * num_comp;
687e7f679fcSJeremy L Thompson   (*rstr)->num_block  = num_elem;
688e7f679fcSJeremy L Thompson   (*rstr)->block_size = 1;
689fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type  = CEED_RESTRICTION_STRIDED;
6902b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
6912b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
692fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
693e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
694d7b241e6Sjeremylt }
695d7b241e6Sjeremylt 
696d7b241e6Sjeremylt /**
6973ac8f562SJeremy L Thompson   @brief Create a points CeedElemRestriction, for restricting for restricting from a all local points to the current element in which they are
6983ac8f562SJeremy L Thompson  located.
6993ac8f562SJeremy L Thompson 
7003ac8f562SJeremy L Thompson   The offsets array is arranged as
7013ac8f562SJeremy L Thompson 
7023ac8f562SJeremy L Thompson   element_0_start_index
7033ac8f562SJeremy L Thompson   element_1_start_index
7043ac8f562SJeremy L Thompson   ...
7053ac8f562SJeremy L Thompson   element_n_start_index
7063ac8f562SJeremy L Thompson   element_n_stop_index
7073ac8f562SJeremy L Thompson   element_0_point_0
7083ac8f562SJeremy L Thompson   element_0_point_1
7093ac8f562SJeremy L Thompson   ...
7103ac8f562SJeremy L Thompson 
7113ac8f562SJeremy L Thompson   @param[in]  ceed          Ceed object where the CeedElemRestriction will be created
7123ac8f562SJeremy L Thompson   @param[in]  num_elem      Number of elements described in the @a offsets array
7133ac8f562SJeremy L Thompson   @param[in]  num_points    Number of points described in the @a offsets array
7143ac8f562SJeremy L Thompson   @param[in]  num_comp      Number of field components per interpolation node (1 for scalar fields).
7153ac8f562SJeremy L Thompson                               Components are assumed to be contiguous by point.
7163ac8f562SJeremy L Thompson   @param[in]  l_size        The size of the L-vector.
7173ac8f562SJeremy L Thompson                               This vector may be larger than the elements and fields given by this restriction.
7183ac8f562SJeremy L Thompson   @param[in]  mem_type      Memory type of the @a offsets array, see CeedMemType
7193ac8f562SJeremy L Thompson   @param[in]  copy_mode     Copy mode for the @a offsets array, see CeedCopyMode
7203ac8f562SJeremy L Thompson   @param[in]  offsets       Array of size num_elem + 1 + num_points.
7213ac8f562SJeremy L Thompson                               The first portion of the offsets array holds the ranges of indices corresponding to each element.
7223ac8f562SJeremy L Thompson                               The second portion holds the indices for each element.
7233ac8f562SJeremy L Thompson   @param[out] rstr          Address of the variable where the newly created CeedElemRestriction will be stored
7243ac8f562SJeremy L Thompson 
7253ac8f562SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
7263ac8f562SJeremy L Thompson 
7273ac8f562SJeremy L Thompson   @ref Backend
7283ac8f562SJeremy L Thompson  **/
7293ac8f562SJeremy L Thompson int CeedElemRestrictionCreateAtPoints(Ceed ceed, CeedInt num_elem, CeedInt num_points, CeedInt num_comp, CeedSize l_size, CeedMemType mem_type,
7303ac8f562SJeremy L Thompson                                       CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
7313ac8f562SJeremy L Thompson   if (!ceed->ElemRestrictionCreateAtPoints) {
7323ac8f562SJeremy L Thompson     Ceed delegate;
7333ac8f562SJeremy L Thompson 
7343ac8f562SJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
7353ac8f562SJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateAtPoints");
7363ac8f562SJeremy L Thompson     CeedCall(CeedElemRestrictionCreateAtPoints(delegate, num_elem, num_points, num_comp, l_size, mem_type, copy_mode, offsets, rstr));
7373ac8f562SJeremy L Thompson     return CEED_ERROR_SUCCESS;
7383ac8f562SJeremy L Thompson   }
7393ac8f562SJeremy L Thompson 
7403ac8f562SJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
7413ac8f562SJeremy L Thompson   CeedCheck(num_points >= 0, ceed, CEED_ERROR_DIMENSION, "Number of points must be non-negative");
7423ac8f562SJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
7433ac8f562SJeremy L Thompson   CeedCheck(l_size >= num_points * num_comp, ceed, CEED_ERROR_DIMENSION, "L-vector must be at least num_points * num_comp");
7443ac8f562SJeremy L Thompson 
7453ac8f562SJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
7463ac8f562SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
7473ac8f562SJeremy L Thompson   (*rstr)->ref_count  = 1;
7483ac8f562SJeremy L Thompson   (*rstr)->num_elem   = num_elem;
7493ac8f562SJeremy L Thompson   (*rstr)->num_points = num_points;
7503ac8f562SJeremy L Thompson   (*rstr)->num_comp   = num_comp;
7513ac8f562SJeremy L Thompson   (*rstr)->l_size     = l_size;
75205fa913cSJeremy L Thompson   (*rstr)->e_size     = num_points * num_comp;
75305fa913cSJeremy L Thompson   (*rstr)->num_block  = num_elem;
7543ac8f562SJeremy L Thompson   (*rstr)->block_size = 1;
7553ac8f562SJeremy L Thompson   (*rstr)->rstr_type  = CEED_RESTRICTION_POINTS;
7563ac8f562SJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateAtPoints(mem_type, copy_mode, offsets, NULL, NULL, *rstr));
7573ac8f562SJeremy L Thompson   return CEED_ERROR_SUCCESS;
7583ac8f562SJeremy L Thompson }
7593ac8f562SJeremy L Thompson 
7603ac8f562SJeremy L Thompson /**
761b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
762d7b241e6Sjeremylt 
7633ac8f562SJeremy L Thompson   @param[in]  ceed          Ceed object where the CeedElemRestriction will be created
7643ac8f562SJeremy L Thompson   @param[in]  num_elem      Number of elements described in the @a offsets array
765ea61e9acSJeremy L Thompson   @param[in]  elem_size     Size (number of unknowns) per element
766e7f679fcSJeremy L Thompson   @param[in]  block_size    Number of elements in a block
767ea61e9acSJeremy L Thompson   @param[in]  num_comp      Number of field components per interpolation node (1 for scalar fields)
768fcbe8c06SSebastian Grimberg   @param[in]  comp_stride   Stride between components for the same L-vector "node".
769fcbe8c06SSebastian Grimberg                               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.
770fcbe8c06SSebastian Grimberg   @param[in]  l_size        The size of the L-vector.
771fcbe8c06SSebastian Grimberg                               This vector may be larger than the elements and fields given by this restriction.
772ea61e9acSJeremy L Thompson   @param[in]  mem_type      Memory type of the @a offsets array, see CeedMemType
773ea61e9acSJeremy L Thompson   @param[in]  copy_mode     Copy mode for the @a offsets array, see CeedCopyMode
774fcbe8c06SSebastian Grimberg   @param[in]  offsets       Array of shape [@a num_elem, @a elem_size].
775e7f679fcSJeremy L Thompson                               Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i,
776e7f679fcSJeremy L Thompson  where 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1]. The backend will permute and pad this array to the desired ordering
777e7f679fcSJeremy L Thompson  for the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
778ea61e9acSJeremy L Thompson   @param[out] rstr          Address of the variable where the newly created CeedElemRestriction will be stored
779d7b241e6Sjeremylt 
780b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
781dfdf5a53Sjeremylt 
7827a982d89SJeremy L. Thompson   @ref Backend
783b11c1e72Sjeremylt  **/
784e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedInt comp_stride,
7852b730f8bSJeremy L Thompson                                      CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets,
7864ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
7871c66c397SJeremy L Thompson   CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
788d7b241e6Sjeremylt 
7895fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
7905fe0d4faSjeremylt     Ceed delegate;
7916574a04fSJeremy L Thompson 
7922b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
7936402da51SJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
794e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
795e7f679fcSJeremy L Thompson                                               rstr));
796e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
7975fe0d4faSjeremylt   }
798d7b241e6Sjeremylt 
799e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
8006574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
801e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
8026574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
8036574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
804e022e1f8SJeremy L Thompson 
805e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
806e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
807d7b241e6Sjeremylt 
808db002c03SJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
809db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
810d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
811d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
812d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
813d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
814d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
815d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
81605fa913cSJeremy L Thompson   (*rstr)->e_size      = num_block * block_size * elem_size * num_comp;
817e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
818e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
81961a27d74SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_STANDARD;
820e7f679fcSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL, NULL, *rstr));
8211c66c397SJeremy L Thompson   if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
822e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
823d7b241e6Sjeremylt }
824d7b241e6Sjeremylt 
825b11c1e72Sjeremylt /**
82677d1c127SSebastian Grimberg   @brief Create a blocked oriented CeedElemRestriction, typically only called by backends
82777d1c127SSebastian Grimberg 
82877d1c127SSebastian Grimberg   @param[in]  ceed          Ceed object where the CeedElemRestriction will be created.
82977d1c127SSebastian Grimberg   @param[in]  num_elem      Number of elements described in the @a offsets array.
83077d1c127SSebastian Grimberg   @param[in]  elem_size     Size (number of unknowns) per element
831e7f679fcSJeremy L Thompson   @param[in]  block_size    Number of elements in a block
83277d1c127SSebastian Grimberg   @param[in]  num_comp      Number of field components per interpolation node (1 for scalar fields)
833fcbe8c06SSebastian Grimberg   @param[in]  comp_stride   Stride between components for the same L-vector "node".
834fcbe8c06SSebastian Grimberg                               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.
835fcbe8c06SSebastian Grimberg   @param[in]  l_size        The size of the L-vector.
836fcbe8c06SSebastian Grimberg                               This vector may be larger than the elements and fields given by this restriction.
83777d1c127SSebastian Grimberg   @param[in]  mem_type      Memory type of the @a offsets array, see CeedMemType
83877d1c127SSebastian Grimberg   @param[in]  copy_mode     Copy mode for the @a offsets array, see CeedCopyMode
839fcbe8c06SSebastian Grimberg   @param[in]  offsets       Array of shape [@a num_elem, @a elem_size].
840fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
841fcbe8c06SSebastian Grimberg  0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1]. The backend will permute and pad this array to the desired ordering for
842fcbe8c06SSebastian Grimberg  the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
843fcbe8c06SSebastian Grimberg   @param[in]  orients       Array of shape [@a num_elem, @a elem_size] with bool false for positively oriented and true to flip the orientation.
844fcbe8c06SSebastian Grimberg                               Will also be permuted and padded similarly to @a offsets.
84577d1c127SSebastian Grimberg   @param[out] rstr          Address of the variable where the newly created CeedElemRestriction will be stored
84677d1c127SSebastian Grimberg 
84777d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
84877d1c127SSebastian Grimberg 
84977d1c127SSebastian Grimberg   @ref Backend
85077d1c127SSebastian Grimberg  **/
851e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp,
852e7f679fcSJeremy L Thompson                                              CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode,
853e7f679fcSJeremy L Thompson                                              const CeedInt *offsets, const bool *orients, CeedElemRestriction *rstr) {
854e7f679fcSJeremy L Thompson   bool    *block_orients;
8551c66c397SJeremy L Thompson   CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
85677d1c127SSebastian Grimberg 
857fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreateBlocked) {
85877d1c127SSebastian Grimberg     Ceed delegate;
85977d1c127SSebastian Grimberg 
86077d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
861fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
862e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode,
86377d1c127SSebastian Grimberg                                                       offsets, orients, rstr));
86477d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
86577d1c127SSebastian Grimberg   }
86677d1c127SSebastian Grimberg 
86777d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
868e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
86977d1c127SSebastian Grimberg   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
87077d1c127SSebastian Grimberg   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
87177d1c127SSebastian Grimberg 
872e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
873e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_orients));
874e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
875e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOrients(orients, block_orients, num_block, num_elem, block_size, elem_size));
87677d1c127SSebastian Grimberg 
877fcbe8c06SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
878fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
87977d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
88077d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
88177d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
88277d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
88377d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
88477d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
88505fa913cSJeremy L Thompson   (*rstr)->e_size      = num_block * block_size * elem_size * num_comp;
886e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
887e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
888fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_ORIENTED;
889e7f679fcSJeremy L Thompson   CeedCall(
890e7f679fcSJeremy L Thompson       ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, (const bool *)block_orients, NULL, *rstr));
8911c66c397SJeremy L Thompson   if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
89277d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
89377d1c127SSebastian Grimberg }
89477d1c127SSebastian Grimberg 
89577d1c127SSebastian Grimberg /**
89677d1c127SSebastian Grimberg   @brief Create a blocked curl-oriented CeedElemRestriction, typically only called by backends
89777d1c127SSebastian Grimberg 
89877d1c127SSebastian Grimberg   @param[in]  ceed           Ceed object where the CeedElemRestriction will be created.
89977d1c127SSebastian Grimberg   @param[in]  num_elem       Number of elements described in the @a offsets array.
90077d1c127SSebastian Grimberg   @param[in]  elem_size      Size (number of unknowns) per element
901e7f679fcSJeremy L Thompson   @param[in]  block_size     Number of elements in a block
90277d1c127SSebastian Grimberg   @param[in]  num_comp       Number of field components per interpolation node (1 for scalar fields)
903fcbe8c06SSebastian Grimberg   @param[in]  comp_stride    Stride between components for the same L-vector "node".
904fcbe8c06SSebastian Grimberg                                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.
905fcbe8c06SSebastian Grimberg   @param[in]  l_size         The size of the L-vector.
906fcbe8c06SSebastian Grimberg                                This vector may be larger than the elements and fields given by this restriction.
90777d1c127SSebastian Grimberg   @param[in]  mem_type       Memory type of the @a offsets array, see CeedMemType
90877d1c127SSebastian Grimberg   @param[in]  copy_mode      Copy mode for the @a offsets array, see CeedCopyMode
909fcbe8c06SSebastian Grimberg   @param[in]  offsets        Array of shape [@a num_elem, @a elem_size].
910fcbe8c06SSebastian Grimberg                              Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i,
911fcbe8c06SSebastian Grimberg where 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1]. The backend will permute and pad this array to the desired ordering
912fcbe8c06SSebastian Grimberg for the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
9137c1dbaffSSebastian Grimberg   @param[in]  curl_orients Array of shape [@a num_elem, @a 3 * elem_size] representing a row-major tridiagonal matrix (curl_orients[i * 3 * elem_size]
9147c1dbaffSSebastian Grimberg = curl_orients[(i + 1) * 3 * elem_size - 1] = 0, where 0 <= i < @a num_elem) which is applied to the element unknowns upon restriction. This
9157c1dbaffSSebastian Grimberg orientation matrix allows for pairs of face degrees of freedom on elements for H(curl) spaces to be coupled in the element restriction operation,
9167c1dbaffSSebastian Grimberg which is a way to resolve face orientation issues for 3D meshes (https://dl.acm.org/doi/pdf/10.1145/3524456). Will also be permuted and padded
9177c1dbaffSSebastian Grimberg similarly to @a offsets.
91877d1c127SSebastian Grimberg   @param[out] rstr           Address of the variable where the newly created CeedElemRestriction will be stored
91977d1c127SSebastian Grimberg 
92077d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
92177d1c127SSebastian Grimberg 
92277d1c127SSebastian Grimberg   @ref Backend
92377d1c127SSebastian Grimberg  **/
924e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp,
92577d1c127SSebastian Grimberg                                                  CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode,
9260c73c039SSebastian Grimberg                                                  const CeedInt *offsets, const CeedInt8 *curl_orients, CeedElemRestriction *rstr) {
927e7f679fcSJeremy L Thompson   CeedInt8 *block_curl_orients;
9281c66c397SJeremy L Thompson   CeedInt  *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
92977d1c127SSebastian Grimberg 
930fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreateBlocked) {
93177d1c127SSebastian Grimberg     Ceed delegate;
93277d1c127SSebastian Grimberg 
93377d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
934fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
935e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedCurlOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type,
936e7f679fcSJeremy L Thompson                                                           copy_mode, offsets, curl_orients, rstr));
93777d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
93877d1c127SSebastian Grimberg   }
93977d1c127SSebastian Grimberg 
940e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
94177d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
942e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
94377d1c127SSebastian Grimberg   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
94477d1c127SSebastian Grimberg   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
94577d1c127SSebastian Grimberg 
946e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
947e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * 3 * elem_size, &block_curl_orients));
948e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
949e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadCurlOrients(curl_orients, block_curl_orients, num_block, num_elem, block_size, 3 * elem_size));
95077d1c127SSebastian Grimberg 
951fcbe8c06SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
952fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
95377d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
95477d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
95577d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
95677d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
95777d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
95877d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
95905fa913cSJeremy L Thompson   (*rstr)->e_size      = num_block * block_size * elem_size * num_comp;
960e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
961e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
962fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_CURL_ORIENTED;
963e7f679fcSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL,
964e7f679fcSJeremy L Thompson                                               (const CeedInt8 *)block_curl_orients, *rstr));
9651c66c397SJeremy L Thompson   if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
96677d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
96777d1c127SSebastian Grimberg }
96877d1c127SSebastian Grimberg 
96977d1c127SSebastian Grimberg /**
97077d1c127SSebastian Grimberg   @brief Create a blocked strided CeedElemRestriction, typically only called by backends
9717509a596Sjeremylt 
972ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
973ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described by the restriction
974ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
975e7f679fcSJeremy L Thompson   @param[in]  block_size  Number of elements in a block
976ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
977fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
978fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
979fcbe8c06SSebastian Grimberg   @param[in]  strides     Array for strides between [nodes, components, elements].
980fcbe8c06SSebastian Grimberg                             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].
981fcbe8c06SSebastian Grimberg                             @a CEED_STRIDES_BACKEND may be used with vectors created by a Ceed backend.
982ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
9837509a596Sjeremylt 
9847509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
9857509a596Sjeremylt 
9867a982d89SJeremy L. Thompson   @ref User
9877509a596Sjeremylt **/
988e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedSize l_size,
9898621c6c6SJeremy L Thompson                                             const CeedInt strides[3], CeedElemRestriction *rstr) {
990e7f679fcSJeremy L Thompson   CeedInt num_block = (num_elem / block_size) + !!(num_elem % block_size);
9917509a596Sjeremylt 
9927509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
9937509a596Sjeremylt     Ceed delegate;
9946574a04fSJeremy L Thompson 
9952b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
996fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
997e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, block_size, num_comp, l_size, strides, rstr));
998e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
9997509a596Sjeremylt   }
10007509a596Sjeremylt 
1001e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
10026574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
1003e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
10046574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
1005e7f679fcSJeremy L Thompson   CeedCheck(l_size >= num_elem * elem_size * num_comp, ceed, CEED_ERROR_DIMENSION, "L-vector size must be at least num_elem * elem_size * num_comp");
1006e022e1f8SJeremy L Thompson 
10072b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
1008db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
1009d1d35e2fSjeremylt   (*rstr)->ref_count  = 1;
1010d1d35e2fSjeremylt   (*rstr)->num_elem   = num_elem;
1011d1d35e2fSjeremylt   (*rstr)->elem_size  = elem_size;
1012d1d35e2fSjeremylt   (*rstr)->num_comp   = num_comp;
1013d1d35e2fSjeremylt   (*rstr)->l_size     = l_size;
101405fa913cSJeremy L Thompson   (*rstr)->e_size     = num_block * block_size * elem_size * num_comp;
1015e7f679fcSJeremy L Thompson   (*rstr)->num_block  = num_block;
1016e7f679fcSJeremy L Thompson   (*rstr)->block_size = block_size;
1017fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type  = CEED_RESTRICTION_STRIDED;
10182b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
10192b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
1020fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
1021e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
10227509a596Sjeremylt }
10237509a596Sjeremylt 
10247509a596Sjeremylt /**
10257c1dbaffSSebastian Grimberg   @brief Copy the pointer to a CeedElemRestriction and set `CeedElemRestrictionApply()` implementation to use the unsigned version.
1026c17ec2beSJeremy L Thompson 
1027c17ec2beSJeremy L Thompson   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
1028c17ec2beSJeremy L Thompson 
1029c17ec2beSJeremy L Thompson   @param[in]     rstr          CeedElemRestriction to create unsigned reference to
1030c17ec2beSJeremy L Thompson   @param[in,out] rstr_unsigned Variable to store unsigned CeedElemRestriction
1031c17ec2beSJeremy L Thompson 
1032c17ec2beSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1033c17ec2beSJeremy L Thompson 
1034c17ec2beSJeremy L Thompson   @ref User
1035c17ec2beSJeremy L Thompson **/
1036c17ec2beSJeremy L Thompson int CeedElemRestrictionCreateUnsignedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unsigned) {
1037c17ec2beSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr_unsigned));
1038c17ec2beSJeremy L Thompson 
1039c17ec2beSJeremy L Thompson   // Copy old rstr
1040c17ec2beSJeremy L Thompson   memcpy(*rstr_unsigned, rstr, sizeof(struct CeedElemRestriction_private));
1041c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ceed = NULL;
1042c17ec2beSJeremy L Thompson   CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unsigned)->ceed));
1043c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ref_count = 1;
1044c17ec2beSJeremy L Thompson   (*rstr_unsigned)->strides   = NULL;
1045c17ec2beSJeremy L Thompson   if (rstr->strides) {
1046c17ec2beSJeremy L Thompson     CeedCall(CeedMalloc(3, &(*rstr_unsigned)->strides));
1047c17ec2beSJeremy L Thompson     for (CeedInt i = 0; i < 3; i++) (*rstr_unsigned)->strides[i] = rstr->strides[i];
1048c17ec2beSJeremy L Thompson   }
10497c1dbaffSSebastian Grimberg   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unsigned)->rstr_base));
1050c17ec2beSJeremy L Thompson 
1051c17ec2beSJeremy L Thompson   // Override Apply
1052c17ec2beSJeremy L Thompson   (*rstr_unsigned)->Apply = rstr->ApplyUnsigned;
1053c17ec2beSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1054c17ec2beSJeremy L Thompson }
1055c17ec2beSJeremy L Thompson 
1056c17ec2beSJeremy L Thompson /**
10577c1dbaffSSebastian Grimberg   @brief Copy the pointer to a CeedElemRestriction and set `CeedElemRestrictionApply()` implementation to use the unoriented version.
10587c1dbaffSSebastian Grimberg 
10597c1dbaffSSebastian Grimberg   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
10607c1dbaffSSebastian Grimberg 
10617c1dbaffSSebastian Grimberg   @param[in]     rstr            CeedElemRestriction to create unoriented reference to
10627c1dbaffSSebastian Grimberg   @param[in,out] rstr_unoriented Variable to store unoriented CeedElemRestriction
10637c1dbaffSSebastian Grimberg 
10647c1dbaffSSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
10657c1dbaffSSebastian Grimberg 
10667c1dbaffSSebastian Grimberg   @ref User
10677c1dbaffSSebastian Grimberg **/
10687c1dbaffSSebastian Grimberg int CeedElemRestrictionCreateUnorientedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unoriented) {
10697c1dbaffSSebastian Grimberg   CeedCall(CeedCalloc(1, rstr_unoriented));
10707c1dbaffSSebastian Grimberg 
10717c1dbaffSSebastian Grimberg   // Copy old rstr
10727c1dbaffSSebastian Grimberg   memcpy(*rstr_unoriented, rstr, sizeof(struct CeedElemRestriction_private));
10737c1dbaffSSebastian Grimberg   (*rstr_unoriented)->ceed = NULL;
10747c1dbaffSSebastian Grimberg   CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unoriented)->ceed));
10757c1dbaffSSebastian Grimberg   (*rstr_unoriented)->ref_count = 1;
10767c1dbaffSSebastian Grimberg   (*rstr_unoriented)->strides   = NULL;
10777c1dbaffSSebastian Grimberg   if (rstr->strides) {
10787c1dbaffSSebastian Grimberg     CeedCall(CeedMalloc(3, &(*rstr_unoriented)->strides));
10797c1dbaffSSebastian Grimberg     for (CeedInt i = 0; i < 3; i++) (*rstr_unoriented)->strides[i] = rstr->strides[i];
10807c1dbaffSSebastian Grimberg   }
10817c1dbaffSSebastian Grimberg   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unoriented)->rstr_base));
10827c1dbaffSSebastian Grimberg 
10837c1dbaffSSebastian Grimberg   // Override Apply
10847c1dbaffSSebastian Grimberg   (*rstr_unoriented)->Apply = rstr->ApplyUnoriented;
10857c1dbaffSSebastian Grimberg   return CEED_ERROR_SUCCESS;
10867c1dbaffSSebastian Grimberg }
10877c1dbaffSSebastian Grimberg 
10887c1dbaffSSebastian Grimberg /**
1089ea61e9acSJeremy L Thompson   @brief Copy the pointer to a CeedElemRestriction.
10909fd66db6SSebastian Grimberg 
1091ea61e9acSJeremy L Thompson   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
10929560d06aSjeremylt 
10939fd66db6SSebastian Grimberg   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.
10949fd66db6SSebastian Grimberg         This CeedElemRestriction will be destroyed if `rstr_copy` is the only reference to this CeedElemRestriction.
1095ea61e9acSJeremy L Thompson 
1096ea61e9acSJeremy L Thompson   @param[in]     rstr      CeedElemRestriction to copy reference to
1097ea61e9acSJeremy L Thompson   @param[in,out] rstr_copy Variable to store copied reference
10989560d06aSjeremylt 
10999560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
11009560d06aSjeremylt 
11019560d06aSjeremylt   @ref User
11029560d06aSjeremylt **/
11032b730f8bSJeremy L Thompson int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_copy) {
1104393ac2cdSJeremy L Thompson   if (rstr != CEED_ELEMRESTRICTION_NONE) CeedCall(CeedElemRestrictionReference(rstr));
11052b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionDestroy(rstr_copy));
11069560d06aSjeremylt   *rstr_copy = rstr;
11079560d06aSjeremylt   return CEED_ERROR_SUCCESS;
11089560d06aSjeremylt }
11099560d06aSjeremylt 
11109560d06aSjeremylt /**
1111b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
1112b11c1e72Sjeremylt 
1113ea61e9acSJeremy L Thompson   @param[in]  rstr  CeedElemRestriction
1114ea61e9acSJeremy L Thompson   @param[out] l_vec The address of the L-vector to be created, or NULL
1115ea61e9acSJeremy L Thompson   @param[out] e_vec The address of the E-vector to be created, or NULL
1116b11c1e72Sjeremylt 
1117b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1118dfdf5a53Sjeremylt 
11197a982d89SJeremy L. Thompson   @ref User
1120b11c1e72Sjeremylt **/
11212b730f8bSJeremy L Thompson int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, CeedVector *e_vec) {
1122d2643443SJeremy L Thompson   CeedSize e_size, l_size;
1123*48acf710SJeremy L Thompson 
1124d1d35e2fSjeremylt   l_size = rstr->l_size;
1125*48acf710SJeremy L Thompson   if (rstr->rstr_type == CEED_RESTRICTION_POINTS) {
1126*48acf710SJeremy L Thompson     e_size = rstr->num_points * rstr->num_comp;
1127*48acf710SJeremy L Thompson   } else {
1128e7f679fcSJeremy L Thompson     e_size = rstr->num_block * rstr->block_size * rstr->elem_size * rstr->num_comp;
1129*48acf710SJeremy L Thompson   }
11302b730f8bSJeremy L Thompson   if (l_vec) CeedCall(CeedVectorCreate(rstr->ceed, l_size, l_vec));
11312b730f8bSJeremy L Thompson   if (e_vec) CeedCall(CeedVectorCreate(rstr->ceed, e_size, e_vec));
1132e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1133d7b241e6Sjeremylt }
1134d7b241e6Sjeremylt 
1135d7b241e6Sjeremylt /**
1136d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
1137d7b241e6Sjeremylt 
1138ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
1139ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1140ea61e9acSJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
1141fcbe8c06SSebastian Grimberg   @param[out] ru      Output vector (of shape [@a num_elem * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
1142fcbe8c06SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
1143ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
1144b11c1e72Sjeremylt 
1145b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1146dfdf5a53Sjeremylt 
11477a982d89SJeremy L. Thompson   @ref User
1148b11c1e72Sjeremylt **/
11492b730f8bSJeremy L Thompson int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
1150d7b241e6Sjeremylt   CeedInt m, n;
1151d7b241e6Sjeremylt 
1152d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
115305fa913cSJeremy L Thompson     m = rstr->e_size;
1154d1d35e2fSjeremylt     n = rstr->l_size;
1155d7b241e6Sjeremylt   } else {
1156d1d35e2fSjeremylt     m = rstr->l_size;
115705fa913cSJeremy L Thompson     n = rstr->e_size;
1158d7b241e6Sjeremylt   }
115905fa913cSJeremy L Thompson   CeedCheck(n <= u->length, rstr->ceed, CEED_ERROR_DIMENSION,
11606574a04fSJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
116105fa913cSJeremy L Thompson   CeedCheck(m <= ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
11626574a04fSJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
11632b730f8bSJeremy L Thompson   if (rstr->num_elem > 0) CeedCall(rstr->Apply(rstr, t_mode, u, ru, request));
1164e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1165d7b241e6Sjeremylt }
1166d7b241e6Sjeremylt 
1167d7b241e6Sjeremylt /**
11683ac8f562SJeremy L Thompson   @brief Restrict an L-vector of points to a single element or apply its transpose
11693ac8f562SJeremy L Thompson 
11703ac8f562SJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
11716cec60aaSJed Brown   @param[in]  elem    Element number in range 0..@a num_elem
11723ac8f562SJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
11733ac8f562SJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
11746595d053SJeremy L Thompson   @param[out] ru      Output vector (of shape [@a num_points * @a num_comp] when t_mode=@ref CEED_NOTRANSPOSE).
11753ac8f562SJeremy L Thompson                         Ordering of the e-vector is decided by the backend.
11763ac8f562SJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
11773ac8f562SJeremy L Thompson 
11783ac8f562SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
11793ac8f562SJeremy L Thompson 
11803ac8f562SJeremy L Thompson   @ref User
11813ac8f562SJeremy L Thompson **/
118205fa913cSJeremy L Thompson int CeedElemRestrictionApplyAtPointsInElement(CeedElemRestriction rstr, CeedInt elem, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
11833ac8f562SJeremy L Thompson                                               CeedRequest *request) {
11843ac8f562SJeremy L Thompson   CeedInt m, n;
11853ac8f562SJeremy L Thompson 
11863ac8f562SJeremy L Thompson   if (t_mode == CEED_NOTRANSPOSE) {
11873ac8f562SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, elem, &m));
11883ac8f562SJeremy L Thompson     n = rstr->l_size;
11893ac8f562SJeremy L Thompson   } else {
11903ac8f562SJeremy L Thompson     m = rstr->l_size;
11913ac8f562SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, elem, &n));
11923ac8f562SJeremy L Thompson   }
11933ac8f562SJeremy L Thompson   CeedCheck(n <= u->length, rstr->ceed, CEED_ERROR_DIMENSION,
11943ac8f562SJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT
11953ac8f562SJeremy L Thompson             ") for element %" CeedInt_FMT,
11963ac8f562SJeremy L Thompson             u->length, m, n, elem);
11973ac8f562SJeremy L Thompson   CeedCheck(m <= ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
11983ac8f562SJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT
11993ac8f562SJeremy L Thompson             ") for element %" CeedInt_FMT,
12003ac8f562SJeremy L Thompson             ru->length, m, n, elem);
12010930e4e7SJeremy L Thompson   CeedCheck(elem < rstr->num_elem, rstr->ceed, CEED_ERROR_DIMENSION,
12023ac8f562SJeremy L Thompson             "Cannot retrieve element %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", elem, elem, rstr->num_elem);
120305fa913cSJeremy L Thompson   if (rstr->num_elem > 0) CeedCall(rstr->ApplyAtPointsInElement(rstr, elem, t_mode, u, ru, request));
12043ac8f562SJeremy L Thompson   return CEED_ERROR_SUCCESS;
12053ac8f562SJeremy L Thompson }
12063ac8f562SJeremy L Thompson 
12073ac8f562SJeremy L Thompson /**
1208d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
1209be9261b7Sjeremylt 
1210ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
1211e7f679fcSJeremy 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
1212e7f679fcSJeremy L Thompson [3*block_size : 4*block_size]
1213ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1214ea61e9acSJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
1215e7f679fcSJeremy L Thompson   @param[out] ru      Output vector (of shape [@a block_size * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
1216fcbe8c06SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
1217ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
1218be9261b7Sjeremylt 
1219be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
1220be9261b7Sjeremylt 
12217a982d89SJeremy L. Thompson   @ref Backend
1222be9261b7Sjeremylt **/
12232b730f8bSJeremy L Thompson int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
12242b730f8bSJeremy L Thompson                                   CeedRequest *request) {
1225be9261b7Sjeremylt   CeedInt m, n;
1226be9261b7Sjeremylt 
12276402da51SJeremy L Thompson   CeedCheck(rstr->ApplyBlock, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionApplyBlock");
12286402da51SJeremy L Thompson 
1229d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
1230e7f679fcSJeremy L Thompson     m = rstr->block_size * rstr->elem_size * rstr->num_comp;
1231d1d35e2fSjeremylt     n = rstr->l_size;
1232be9261b7Sjeremylt   } else {
1233d1d35e2fSjeremylt     m = rstr->l_size;
1234e7f679fcSJeremy L Thompson     n = rstr->block_size * rstr->elem_size * rstr->num_comp;
1235be9261b7Sjeremylt   }
12366574a04fSJeremy L Thompson   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
12376574a04fSJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
12386574a04fSJeremy L Thompson   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
12396574a04fSJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
1240e7f679fcSJeremy L Thompson   CeedCheck(rstr->block_size * block <= rstr->num_elem, rstr->ceed, CEED_ERROR_DIMENSION,
1241e7f679fcSJeremy L Thompson             "Cannot retrieve block %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", block, rstr->block_size * block,
12426574a04fSJeremy L Thompson             rstr->num_elem);
12432b730f8bSJeremy L Thompson   CeedCall(rstr->ApplyBlock(rstr, block, t_mode, u, ru, request));
1244e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1245be9261b7Sjeremylt }
1246be9261b7Sjeremylt 
1247be9261b7Sjeremylt /**
1248b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedElemRestriction
1249b7c9bbdaSJeremy L Thompson 
1250ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
1251b7c9bbdaSJeremy L Thompson   @param[out] ceed Variable to store Ceed
1252b7c9bbdaSJeremy L Thompson 
1253b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1254b7c9bbdaSJeremy L Thompson 
1255b7c9bbdaSJeremy L Thompson   @ref Advanced
1256b7c9bbdaSJeremy L Thompson **/
1257b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
1258b7c9bbdaSJeremy L Thompson   *ceed = rstr->ceed;
1259b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1260b7c9bbdaSJeremy L Thompson }
1261b7c9bbdaSJeremy L Thompson 
1262b7c9bbdaSJeremy L Thompson /**
1263d979a051Sjeremylt   @brief Get the L-vector component stride
1264a681ae63Sjeremylt 
1265ea61e9acSJeremy L Thompson   @param[in]  rstr        CeedElemRestriction
1266d1d35e2fSjeremylt   @param[out] comp_stride Variable to store component stride
1267a681ae63Sjeremylt 
1268a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1269a681ae63Sjeremylt 
1270b7c9bbdaSJeremy L Thompson   @ref Advanced
1271a681ae63Sjeremylt **/
12722b730f8bSJeremy L Thompson int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, CeedInt *comp_stride) {
1273d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
1274e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1275a681ae63Sjeremylt }
1276a681ae63Sjeremylt 
1277a681ae63Sjeremylt /**
1278a681ae63Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
1279a681ae63Sjeremylt 
1280ea61e9acSJeremy L Thompson   @param[in] rstr      CeedElemRestriction
1281d1d35e2fSjeremylt   @param[out] num_elem Variable to store number of elements
1282a681ae63Sjeremylt 
1283a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1284a681ae63Sjeremylt 
1285b7c9bbdaSJeremy L Thompson   @ref Advanced
1286a681ae63Sjeremylt **/
12872b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, CeedInt *num_elem) {
1288d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
1289e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1290a681ae63Sjeremylt }
1291a681ae63Sjeremylt 
1292a681ae63Sjeremylt /**
1293a681ae63Sjeremylt   @brief Get the size of elements in the CeedElemRestriction
1294a681ae63Sjeremylt 
1295ea61e9acSJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
1296d1d35e2fSjeremylt   @param[out] elem_size Variable to store size of elements
1297a681ae63Sjeremylt 
1298a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1299a681ae63Sjeremylt 
1300b7c9bbdaSJeremy L Thompson   @ref Advanced
1301a681ae63Sjeremylt **/
13022b730f8bSJeremy L Thompson int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, CeedInt *elem_size) {
1303d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
13042c7e7413SJeremy L Thompson   return CEED_ERROR_SUCCESS;
13052c7e7413SJeremy L Thompson }
13062c7e7413SJeremy L Thompson 
13072c7e7413SJeremy L Thompson /**
130807d5dec1SJeremy L Thompson 
130907d5dec1SJeremy L Thompson   @brief Get the number of points in the l-vector for a points CeedElemRestriction
131007d5dec1SJeremy L Thompson 
131107d5dec1SJeremy L Thompson   @param[in]  rstr       CeedElemRestriction
131207d5dec1SJeremy L Thompson   @param[out] num_points The number of points in the l-vector
131307d5dec1SJeremy L Thompson 
131407d5dec1SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
131507d5dec1SJeremy L Thompson 
1316c63574e3SJeremy L Thompson   @ref User
131707d5dec1SJeremy L Thompson **/
131807d5dec1SJeremy L Thompson int CeedElemRestrictionGetNumPoints(CeedElemRestriction rstr, CeedInt *num_points) {
131907d5dec1SJeremy L Thompson   Ceed ceed;
132007d5dec1SJeremy L Thompson 
132107d5dec1SJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
132207d5dec1SJeremy L Thompson   CeedCheck(rstr->rstr_type == CEED_RESTRICTION_POINTS, ceed, CEED_ERROR_INCOMPATIBLE,
132307d5dec1SJeremy L Thompson             "Can only retrieve the number of points for a points CeedElemRestriction");
132407d5dec1SJeremy L Thompson 
132507d5dec1SJeremy L Thompson   *num_points = rstr->num_points;
132607d5dec1SJeremy L Thompson   return CEED_ERROR_SUCCESS;
132707d5dec1SJeremy L Thompson }
132807d5dec1SJeremy L Thompson 
132907d5dec1SJeremy L Thompson /**
133007d5dec1SJeremy L Thompson 
133107d5dec1SJeremy L Thompson   @brief Get the number of points in an element of a points CeedElemRestriction
133207d5dec1SJeremy L Thompson 
133307d5dec1SJeremy L Thompson   @param[in]  rstr       CeedElemRestriction
133407d5dec1SJeremy L Thompson   @param[in]  elem       Index number of element to retrieve the number of points for
133507d5dec1SJeremy L Thompson   @param[out] num_points The number of points in the element at index elem
133607d5dec1SJeremy L Thompson 
133707d5dec1SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
133807d5dec1SJeremy L Thompson 
1339c63574e3SJeremy L Thompson   @ref User
134007d5dec1SJeremy L Thompson **/
134107d5dec1SJeremy L Thompson int CeedElemRestrictionGetNumPointsInElement(CeedElemRestriction rstr, CeedInt elem, CeedInt *num_points) {
134207d5dec1SJeremy L Thompson   Ceed           ceed;
134307d5dec1SJeremy L Thompson   const CeedInt *offsets;
134407d5dec1SJeremy L Thompson 
134507d5dec1SJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
134607d5dec1SJeremy L Thompson   CeedCheck(rstr->rstr_type == CEED_RESTRICTION_POINTS, ceed, CEED_ERROR_INCOMPATIBLE,
134707d5dec1SJeremy L Thompson             "Can only retrieve the number of points for a points CeedElemRestriction");
134807d5dec1SJeremy L Thompson 
134907d5dec1SJeremy L Thompson   CeedCall(CeedElemRestrictionGetOffsets(rstr, CEED_MEM_HOST, &offsets));
135007d5dec1SJeremy L Thompson   *num_points = offsets[elem + 1] - offsets[elem];
135107d5dec1SJeremy L Thompson   CeedCall(CeedElemRestrictionRestoreOffsets(rstr, &offsets));
135207d5dec1SJeremy L Thompson   return CEED_ERROR_SUCCESS;
135307d5dec1SJeremy L Thompson }
135407d5dec1SJeremy L Thompson 
135507d5dec1SJeremy L Thompson /**
13562c7e7413SJeremy L Thompson   @brief Get the maximum number of points in an element for a CeedElemRestriction at points
13572c7e7413SJeremy L Thompson 
13582c7e7413SJeremy L Thompson   @param[in]  rstr       CeedElemRestriction
13592c7e7413SJeremy L Thompson   @param[out] max_points Variable to store size of elements
13602c7e7413SJeremy L Thompson 
13612c7e7413SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
13622c7e7413SJeremy L Thompson 
13632c7e7413SJeremy L Thompson   @ref Advanced
13642c7e7413SJeremy L Thompson **/
13652c7e7413SJeremy L Thompson int CeedElemRestrictionGetMaxPointsInElement(CeedElemRestriction rstr, CeedInt *max_points) {
13662c7e7413SJeremy L Thompson   Ceed                ceed;
13672c7e7413SJeremy L Thompson   CeedInt             num_elem;
13682c7e7413SJeremy L Thompson   CeedRestrictionType rstr_type;
13692c7e7413SJeremy L Thompson 
13702c7e7413SJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
13712c7e7413SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
13722c7e7413SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, ceed, CEED_ERROR_INCOMPATIBLE,
13732c7e7413SJeremy L Thompson             "Cannot compute max points for a CeedElemRestriction that does not use points");
13742c7e7413SJeremy L Thompson 
13752c7e7413SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
13762c7e7413SJeremy L Thompson   *max_points = 0;
13772c7e7413SJeremy L Thompson   for (CeedInt e = 0; e < num_elem; e++) {
13782c7e7413SJeremy L Thompson     CeedInt num_points;
13792c7e7413SJeremy L Thompson 
13802c7e7413SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, e, &num_points));
13812c7e7413SJeremy L Thompson     *max_points = CeedIntMax(num_points, *max_points);
13822c7e7413SJeremy L Thompson   }
1383e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1384a681ae63Sjeremylt }
1385a681ae63Sjeremylt 
1386a681ae63Sjeremylt /**
1387d979a051Sjeremylt   @brief Get the size of the l-vector for a CeedElemRestriction
1388a681ae63Sjeremylt 
1389ea61e9acSJeremy L Thompson   @param[in]  rstr   CeedElemRestriction
1390d1d35e2fSjeremylt   @param[out] l_size Variable to store number of nodes
1391a681ae63Sjeremylt 
1392a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1393a681ae63Sjeremylt 
1394b7c9bbdaSJeremy L Thompson   @ref Advanced
1395a681ae63Sjeremylt **/
13962b730f8bSJeremy L Thompson int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, CeedSize *l_size) {
1397d1d35e2fSjeremylt   *l_size = rstr->l_size;
1398e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1399a681ae63Sjeremylt }
1400a681ae63Sjeremylt 
1401a681ae63Sjeremylt /**
1402ea61e9acSJeremy L Thompson   @brief Get the number of components in the elements of a CeedElemRestriction
1403a681ae63Sjeremylt 
1404ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction
1405d1d35e2fSjeremylt   @param[out] num_comp Variable to store number of components
1406a681ae63Sjeremylt 
1407a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1408a681ae63Sjeremylt 
1409b7c9bbdaSJeremy L Thompson   @ref Advanced
1410a681ae63Sjeremylt **/
14112b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, CeedInt *num_comp) {
1412d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
1413e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1414a681ae63Sjeremylt }
1415a681ae63Sjeremylt 
1416a681ae63Sjeremylt /**
1417a681ae63Sjeremylt   @brief Get the number of blocks in a CeedElemRestriction
1418a681ae63Sjeremylt 
1419ea61e9acSJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
1420d1d35e2fSjeremylt   @param[out] num_block Variable to store number of blocks
1421a681ae63Sjeremylt 
1422a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1423a681ae63Sjeremylt 
1424b7c9bbdaSJeremy L Thompson   @ref Advanced
1425a681ae63Sjeremylt **/
14262b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, CeedInt *num_block) {
1427e7f679fcSJeremy L Thompson   *num_block = rstr->num_block;
1428e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1429a681ae63Sjeremylt }
1430a681ae63Sjeremylt 
1431a681ae63Sjeremylt /**
1432a681ae63Sjeremylt   @brief Get the size of blocks in the CeedElemRestriction
1433a681ae63Sjeremylt 
1434ea61e9acSJeremy L Thompson   @param[in]  rstr       CeedElemRestriction
1435e7f679fcSJeremy L Thompson   @param[out] block_size Variable to store size of blocks
1436a681ae63Sjeremylt 
1437a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1438a681ae63Sjeremylt 
1439b7c9bbdaSJeremy L Thompson   @ref Advanced
1440a681ae63Sjeremylt **/
1441e7f679fcSJeremy L Thompson int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, CeedInt *block_size) {
1442e7f679fcSJeremy L Thompson   *block_size = rstr->block_size;
1443e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1444a681ae63Sjeremylt }
1445a681ae63Sjeremylt 
1446a681ae63Sjeremylt /**
1447d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
14481469ee4dSjeremylt 
1449ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
1450d1d35e2fSjeremylt   @param[out] mult Vector to store multiplicity (of size l_size)
14511469ee4dSjeremylt 
14521469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
14531469ee4dSjeremylt 
14547a982d89SJeremy L. Thompson   @ref User
14551469ee4dSjeremylt **/
14562b730f8bSJeremy L Thompson int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, CeedVector mult) {
1457d1d35e2fSjeremylt   CeedVector e_vec;
14581469ee4dSjeremylt 
145925509ebbSRezgar Shakeri   // Create e_vec to hold intermediate computation in E^T (E 1)
14602b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionCreateVector(rstr, NULL, &e_vec));
14611469ee4dSjeremylt 
146225509ebbSRezgar Shakeri   // Compute e_vec = E * 1
14632b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 1.0));
14642b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, CEED_REQUEST_IMMEDIATE));
146525509ebbSRezgar Shakeri   // Compute multiplicity, mult = E^T * e_vec = E^T (E 1)
14662b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 0.0));
14672b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, CEED_REQUEST_IMMEDIATE));
14681469ee4dSjeremylt   // Cleanup
14692b730f8bSJeremy L Thompson   CeedCall(CeedVectorDestroy(&e_vec));
1470e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
14711469ee4dSjeremylt }
14721469ee4dSjeremylt 
14731469ee4dSjeremylt /**
1474f02ca4a2SJed Brown   @brief View a CeedElemRestriction
1475f02ca4a2SJed Brown 
1476f02ca4a2SJed Brown   @param[in] rstr   CeedElemRestriction to view
1477f02ca4a2SJed Brown   @param[in] stream Stream to write; typically stdout/stderr or a file
1478f02ca4a2SJed Brown 
1479f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
1480f02ca4a2SJed Brown 
14817a982d89SJeremy L. Thompson   @ref User
1482f02ca4a2SJed Brown **/
1483f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
14840930e4e7SJeremy L Thompson   CeedRestrictionType rstr_type;
14850930e4e7SJeremy L Thompson 
14860930e4e7SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
14870930e4e7SJeremy L Thompson 
14880930e4e7SJeremy L Thompson   if (rstr_type == CEED_RESTRICTION_POINTS) {
14890930e4e7SJeremy L Thompson     CeedInt max_points;
14900930e4e7SJeremy L Thompson 
14910930e4e7SJeremy L Thompson     CeedCall(CeedElemRestrictionGetMaxPointsInElement(rstr, &max_points));
14920930e4e7SJeremy L Thompson     fprintf(stream,
14930930e4e7SJeremy L Thompson             "CeedElemRestriction at points from (%td, %" CeedInt_FMT ") to %" CeedInt_FMT " elements with a maximum of %" CeedInt_FMT
14940930e4e7SJeremy L Thompson             " points on an element\n",
14950930e4e7SJeremy L Thompson             rstr->l_size, rstr->num_comp, rstr->num_elem, max_points);
14960930e4e7SJeremy L Thompson   } else {
14977509a596Sjeremylt     char stridesstr[500];
14981c66c397SJeremy L Thompson 
14992b730f8bSJeremy L Thompson     if (rstr->strides) {
15002b730f8bSJeremy L Thompson       sprintf(stridesstr, "[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "]", rstr->strides[0], rstr->strides[1], rstr->strides[2]);
15012b730f8bSJeremy L Thompson     } else {
1502990fdeb6SJeremy L Thompson       sprintf(stridesstr, "%" CeedInt_FMT, rstr->comp_stride);
15032b730f8bSJeremy L Thompson     }
15042b730f8bSJeremy L Thompson     fprintf(stream, "%sCeedElemRestriction from (%td, %" CeedInt_FMT ") to %" CeedInt_FMT " elements with %" CeedInt_FMT " nodes each and %s %s\n",
1505e7f679fcSJeremy L Thompson             rstr->block_size > 1 ? "Blocked " : "", rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
1506d979a051Sjeremylt             rstr->strides ? "strides" : "component stride", stridesstr);
15070930e4e7SJeremy L Thompson   }
1508e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1509f02ca4a2SJed Brown }
1510f02ca4a2SJed Brown 
1511f02ca4a2SJed Brown /**
1512b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
1513b11c1e72Sjeremylt 
1514ea61e9acSJeremy L Thompson   @param[in,out] rstr CeedElemRestriction to destroy
1515b11c1e72Sjeremylt 
1516b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1517dfdf5a53Sjeremylt 
15187a982d89SJeremy L. Thompson   @ref User
1519b11c1e72Sjeremylt **/
15204ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
1521393ac2cdSJeremy L Thompson   if (!*rstr || *rstr == CEED_ELEMRESTRICTION_NONE || --(*rstr)->ref_count > 0) {
1522ad6481ceSJeremy L Thompson     *rstr = NULL;
1523ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
1524ad6481ceSJeremy L Thompson   }
15256574a04fSJeremy L Thompson   CeedCheck((*rstr)->num_readers == 0, (*rstr)->ceed, CEED_ERROR_ACCESS,
15266574a04fSJeremy L Thompson             "Cannot destroy CeedElemRestriction, a process has read access to the offset data");
1527c17ec2beSJeremy L Thompson 
1528c17ec2beSJeremy L Thompson   // Only destroy backend data once between rstr and unsigned copy
15297c1dbaffSSebastian Grimberg   if ((*rstr)->rstr_base) CeedCall(CeedElemRestrictionDestroy(&(*rstr)->rstr_base));
1530c17ec2beSJeremy L Thompson   else if ((*rstr)->Destroy) CeedCall((*rstr)->Destroy(*rstr));
1531c17ec2beSJeremy L Thompson 
15322b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*rstr)->strides));
15332b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*rstr)->ceed));
15342b730f8bSJeremy L Thompson   CeedCall(CeedFree(rstr));
1535e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1536d7b241e6Sjeremylt }
1537d7b241e6Sjeremylt 
1538d7b241e6Sjeremylt /// @}
1539