xref: /libCEED/interface/ceed-elemrestriction.c (revision 61a27d74d4dddda1a6f7c53fa8f97daed16bb150)
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].
280c73c039SSebastian Grimberg   @param[out] blk_offsets Array of permuted and padded array values of shape [@a num_blk, @a elem_size, @a blk_size].
29ea61e9acSJeremy L Thompson   @param[in]  num_blk     Number of blocks
30ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements
31ea61e9acSJeremy L Thompson   @param[in]  blk_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 **/
382b730f8bSJeremy L Thompson int CeedPermutePadOffsets(const CeedInt *offsets, CeedInt *blk_offsets, CeedInt num_blk, CeedInt num_elem, CeedInt blk_size, CeedInt elem_size) {
392b730f8bSJeremy L Thompson   for (CeedInt e = 0; e < num_blk * blk_size; e += blk_size) {
402b730f8bSJeremy L Thompson     for (CeedInt j = 0; j < blk_size; j++) {
412b730f8bSJeremy L Thompson       for (CeedInt k = 0; k < elem_size; k++) {
422b730f8bSJeremy L Thompson         blk_offsets[e * elem_size + k * blk_size + j] = offsets[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
432b730f8bSJeremy L Thompson       }
442b730f8bSJeremy L Thompson     }
452b730f8bSJeremy L Thompson   }
46e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
477a982d89SJeremy L. Thompson }
487a982d89SJeremy L. Thompson 
4977d1c127SSebastian Grimberg /**
5077d1c127SSebastian Grimberg   @brief Permute and pad orientations for a blocked restriction
5177d1c127SSebastian Grimberg 
52fcbe8c06SSebastian Grimberg   @param[in]  orients     Array of shape [@a num_elem, @a elem_size].
530c73c039SSebastian Grimberg   @param[out] blk_orients Array of permuted and padded array values of shape [@a num_blk, @a elem_size, @a blk_size].
5477d1c127SSebastian Grimberg   @param[in]  num_blk     Number of blocks
5577d1c127SSebastian Grimberg   @param[in]  num_elem    Number of elements
5677d1c127SSebastian Grimberg   @param[in]  blk_size    Number of elements in a block
5777d1c127SSebastian Grimberg   @param[in]  elem_size   Size of each element
5877d1c127SSebastian Grimberg 
5977d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
6077d1c127SSebastian Grimberg 
6177d1c127SSebastian Grimberg   @ref Utility
6277d1c127SSebastian Grimberg **/
630c73c039SSebastian Grimberg int CeedPermutePadOrients(const bool *orients, bool *blk_orients, CeedInt num_blk, CeedInt num_elem, CeedInt blk_size, CeedInt elem_size) {
6477d1c127SSebastian Grimberg   for (CeedInt e = 0; e < num_blk * blk_size; e += blk_size) {
6577d1c127SSebastian Grimberg     for (CeedInt j = 0; j < blk_size; j++) {
6677d1c127SSebastian Grimberg       for (CeedInt k = 0; k < elem_size; k++) {
6777d1c127SSebastian Grimberg         blk_orients[e * elem_size + k * blk_size + j] = orients[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
6877d1c127SSebastian Grimberg       }
6977d1c127SSebastian Grimberg     }
7077d1c127SSebastian Grimberg   }
7177d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
7277d1c127SSebastian Grimberg }
7377d1c127SSebastian Grimberg 
740c73c039SSebastian Grimberg /**
750c73c039SSebastian Grimberg   @brief Permute and pad curl-conforming orientations for a blocked restriction
760c73c039SSebastian Grimberg 
770c73c039SSebastian Grimberg   @param[in]  curl_orients     Array of shape [@a num_elem, @a 3 * elem_size].
780c73c039SSebastian Grimberg   @param[out] blk_curl_orients Array of permuted and padded array values of shape [@a num_blk, @a elem_size, @a blk_size].
790c73c039SSebastian Grimberg   @param[in]  num_blk          Number of blocks
800c73c039SSebastian Grimberg   @param[in]  num_elem         Number of elements
810c73c039SSebastian Grimberg   @param[in]  blk_size         Number of elements in a block
820c73c039SSebastian Grimberg   @param[in]  elem_size        Size of each element
830c73c039SSebastian Grimberg 
840c73c039SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
850c73c039SSebastian Grimberg 
860c73c039SSebastian Grimberg   @ref Utility
870c73c039SSebastian Grimberg **/
880c73c039SSebastian Grimberg int CeedPermutePadCurlOrients(const CeedInt8 *curl_orients, CeedInt8 *blk_curl_orients, CeedInt num_blk, CeedInt num_elem, CeedInt blk_size,
890c73c039SSebastian Grimberg                               CeedInt elem_size) {
900c73c039SSebastian Grimberg   for (CeedInt e = 0; e < num_blk * blk_size; e += blk_size) {
910c73c039SSebastian Grimberg     for (CeedInt j = 0; j < blk_size; j++) {
920c73c039SSebastian Grimberg       for (CeedInt k = 0; k < elem_size; k++) {
930c73c039SSebastian Grimberg         blk_curl_orients[e * elem_size + k * blk_size + j] = curl_orients[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
940c73c039SSebastian Grimberg       }
950c73c039SSebastian Grimberg     }
960c73c039SSebastian Grimberg   }
970c73c039SSebastian Grimberg   return CEED_ERROR_SUCCESS;
980c73c039SSebastian Grimberg }
990c73c039SSebastian Grimberg 
1007a982d89SJeremy L. Thompson /// @}
1017a982d89SJeremy L. Thompson 
1027a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1037a982d89SJeremy L. Thompson /// CeedElemRestriction Backend API
1047a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1057a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionBackend
1067a982d89SJeremy L. Thompson /// @{
1077a982d89SJeremy L. Thompson 
1087a982d89SJeremy L. Thompson /**
109fcbe8c06SSebastian Grimberg   @brief Get the type of a CeedElemRestriction
110a681ae63Sjeremylt 
111fcbe8c06SSebastian Grimberg   @param[in]  rstr      CeedElemRestriction
112fcbe8c06SSebastian Grimberg   @param[out] rstr_type Variable to store restriction type
113fcbe8c06SSebastian Grimberg 
114fcbe8c06SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
115fcbe8c06SSebastian Grimberg 
116fcbe8c06SSebastian Grimberg   @ref Backend
117fcbe8c06SSebastian Grimberg **/
118fcbe8c06SSebastian Grimberg int CeedElemRestrictionGetType(CeedElemRestriction rstr, CeedRestrictionType *rstr_type) {
119fcbe8c06SSebastian Grimberg   *rstr_type = rstr->rstr_type;
120fcbe8c06SSebastian Grimberg   return CEED_ERROR_SUCCESS;
121fcbe8c06SSebastian Grimberg }
122fcbe8c06SSebastian Grimberg 
123fcbe8c06SSebastian Grimberg /**
124fcbe8c06SSebastian Grimberg   @brief Get the strided status of a CeedElemRestriction
125fcbe8c06SSebastian Grimberg 
126fcbe8c06SSebastian Grimberg   @param[in]  rstr       CeedElemRestriction
127fcbe8c06SSebastian Grimberg   @param[out] is_strided Variable to store strided status, 1 if strided else 0
128fcbe8c06SSebastian Grimberg **/
129fcbe8c06SSebastian Grimberg int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) {
130fcbe8c06SSebastian Grimberg   *is_strided = (rstr->rstr_type == CEED_RESTRICTION_STRIDED);
131fcbe8c06SSebastian Grimberg   return CEED_ERROR_SUCCESS;
132fcbe8c06SSebastian Grimberg }
133fcbe8c06SSebastian Grimberg 
134fcbe8c06SSebastian Grimberg /**
135a681ae63Sjeremylt   @brief Get the strides of a strided CeedElemRestriction
1367a982d89SJeremy L. Thompson 
137ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
138a681ae63Sjeremylt   @param[out] strides Variable to store strides array
1397a982d89SJeremy L. Thompson 
1407a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1417a982d89SJeremy L. Thompson 
1427a982d89SJeremy L. Thompson   @ref Backend
1437a982d89SJeremy L. Thompson **/
1442b730f8bSJeremy L Thompson int CeedElemRestrictionGetStrides(CeedElemRestriction rstr, CeedInt (*strides)[3]) {
1456574a04fSJeremy L Thompson   CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
1462b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*strides)[i] = rstr->strides[i];
147e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1487a982d89SJeremy L. Thompson }
1497a982d89SJeremy L. Thompson 
1507a982d89SJeremy L. Thompson /**
15177d1c127SSebastian Grimberg   @brief Get the backend stride status of a CeedElemRestriction
15277d1c127SSebastian Grimberg 
15377d1c127SSebastian Grimberg   @param[in]  rstr                 CeedElemRestriction
15477d1c127SSebastian Grimberg   @param[out] has_backend_strides  Variable to store stride status
15577d1c127SSebastian Grimberg 
15677d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
15777d1c127SSebastian Grimberg 
15877d1c127SSebastian Grimberg   @ref Backend
15977d1c127SSebastian Grimberg **/
16077d1c127SSebastian Grimberg int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, bool *has_backend_strides) {
16177d1c127SSebastian Grimberg   CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
16277d1c127SSebastian Grimberg   *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
16377d1c127SSebastian Grimberg                           (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
16477d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
16577d1c127SSebastian Grimberg }
16677d1c127SSebastian Grimberg 
16777d1c127SSebastian Grimberg /**
168bd33150aSjeremylt   @brief Get read-only access to a CeedElemRestriction offsets array by memtype
169bd33150aSjeremylt 
170ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction to retrieve offsets
171fcbe8c06SSebastian Grimberg   @param[in]  mem_type Memory type on which to access the array.
172fcbe8c06SSebastian Grimberg                          If the backend uses a different memory type, this will perform a copy (possibly cached).
173d1d35e2fSjeremylt   @param[out] offsets  Array on memory type mem_type
174bd33150aSjeremylt 
175bd33150aSjeremylt   @return An error code: 0 - success, otherwise - failure
176bd33150aSjeremylt 
177bd33150aSjeremylt   @ref User
178bd33150aSjeremylt **/
1792b730f8bSJeremy L Thompson int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) {
1807c1dbaffSSebastian Grimberg   if (rstr->rstr_base) {
1817c1dbaffSSebastian Grimberg     CeedCall(CeedElemRestrictionGetOffsets(rstr->rstr_base, mem_type, offsets));
182c17ec2beSJeremy L Thompson   } else {
1836574a04fSJeremy L Thompson     CeedCheck(rstr->GetOffsets, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetOffsets");
1842b730f8bSJeremy L Thompson     CeedCall(rstr->GetOffsets(rstr, mem_type, offsets));
185d1d35e2fSjeremylt     rstr->num_readers++;
186c17ec2beSJeremy L Thompson   }
187e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
188430758c8SJeremy L Thompson }
189430758c8SJeremy L Thompson 
190430758c8SJeremy L Thompson /**
191430758c8SJeremy L Thompson   @brief Restore an offsets array obtained using CeedElemRestrictionGetOffsets()
192430758c8SJeremy L Thompson 
193ea61e9acSJeremy L Thompson   @param[in] rstr    CeedElemRestriction to restore
194ea61e9acSJeremy L Thompson   @param[in] offsets Array of offset data
195430758c8SJeremy L Thompson 
196430758c8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
197430758c8SJeremy L Thompson 
198430758c8SJeremy L Thompson   @ref User
199430758c8SJeremy L Thompson **/
2002b730f8bSJeremy L Thompson int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr, const CeedInt **offsets) {
2017c1dbaffSSebastian Grimberg   if (rstr->rstr_base) {
2027c1dbaffSSebastian Grimberg     CeedCall(CeedElemRestrictionRestoreOffsets(rstr->rstr_base, offsets));
203c17ec2beSJeremy L Thompson   } else {
204430758c8SJeremy L Thompson     *offsets = NULL;
205d1d35e2fSjeremylt     rstr->num_readers--;
206c17ec2beSJeremy L Thompson   }
207e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
208bd33150aSjeremylt }
209bd33150aSjeremylt 
210bd33150aSjeremylt /**
21177d1c127SSebastian Grimberg   @brief Get read-only access to a CeedElemRestriction orientations array by memtype
2123ac43b2cSJeremy L Thompson 
21377d1c127SSebastian Grimberg   @param[in]  rstr     CeedElemRestriction to retrieve orientations
214fcbe8c06SSebastian Grimberg   @param[in]  mem_type Memory type on which to access the array.
215fcbe8c06SSebastian Grimberg                          If the backend uses a different memory type, this will perform a copy (possibly cached).
21677d1c127SSebastian Grimberg   @param[out] orients  Array on memory type mem_type
2173ac43b2cSJeremy L Thompson 
2183ac43b2cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2193ac43b2cSJeremy L Thompson 
22077d1c127SSebastian Grimberg   @ref User
2213ac43b2cSJeremy L Thompson **/
22277d1c127SSebastian Grimberg int CeedElemRestrictionGetOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const bool **orients) {
223fcbe8c06SSebastian Grimberg   CeedCheck(rstr->GetOrientations, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetOrientations");
22477d1c127SSebastian Grimberg   CeedCall(rstr->GetOrientations(rstr, mem_type, orients));
22577d1c127SSebastian Grimberg   rstr->num_readers++;
226e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2273ac43b2cSJeremy L Thompson }
2283ac43b2cSJeremy L Thompson 
2293ac43b2cSJeremy L Thompson /**
23077d1c127SSebastian Grimberg   @brief Restore an orientations array obtained using CeedElemRestrictionGetOrientations()
231b435c5a6Srezgarshakeri 
23277d1c127SSebastian Grimberg   @param[in] rstr    CeedElemRestriction to restore
23377d1c127SSebastian Grimberg   @param[in] orients Array of orientation data
234b435c5a6Srezgarshakeri 
235b435c5a6Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
236b435c5a6Srezgarshakeri 
23777d1c127SSebastian Grimberg   @ref User
238b435c5a6Srezgarshakeri **/
23977d1c127SSebastian Grimberg int CeedElemRestrictionRestoreOrientations(CeedElemRestriction rstr, const bool **orients) {
24077d1c127SSebastian Grimberg   *orients = NULL;
24177d1c127SSebastian Grimberg   rstr->num_readers--;
242b435c5a6Srezgarshakeri   return CEED_ERROR_SUCCESS;
243b435c5a6Srezgarshakeri }
244b435c5a6Srezgarshakeri 
245b435c5a6Srezgarshakeri /**
24677d1c127SSebastian Grimberg   @brief Get read-only access to a CeedElemRestriction curl-conforming orientations array by memtype
2477a982d89SJeremy L. Thompson 
24877d1c127SSebastian Grimberg   @param[in]  rstr         CeedElemRestriction to retrieve curl-conforming orientations
249fcbe8c06SSebastian Grimberg   @param[in]  mem_type     Memory type on which to access the array.
250fcbe8c06SSebastian Grimberg                              If the backend uses a different memory type, this will perform a copy (possibly cached).
25177d1c127SSebastian Grimberg   @param[out] curl_orients Array on memory type mem_type
2527a982d89SJeremy L. Thompson 
2537a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2547a982d89SJeremy L. Thompson 
25577d1c127SSebastian Grimberg   @ref User
2567a982d89SJeremy L. Thompson **/
2570c73c039SSebastian Grimberg int CeedElemRestrictionGetCurlOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt8 **curl_orients) {
258fcbe8c06SSebastian Grimberg   CeedCheck(rstr->GetCurlOrientations, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetCurlOrientations");
25977d1c127SSebastian Grimberg   CeedCall(rstr->GetCurlOrientations(rstr, mem_type, curl_orients));
26077d1c127SSebastian Grimberg   rstr->num_readers++;
26177d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
26277d1c127SSebastian Grimberg }
26377d1c127SSebastian Grimberg 
26477d1c127SSebastian Grimberg /**
26577d1c127SSebastian Grimberg   @brief Restore an orientations array obtained using CeedElemRestrictionGetCurlOrientations()
26677d1c127SSebastian Grimberg 
26777d1c127SSebastian Grimberg   @param[in] rstr         CeedElemRestriction to restore
26877d1c127SSebastian Grimberg   @param[in] curl_orients Array of orientation data
26977d1c127SSebastian Grimberg 
27077d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
27177d1c127SSebastian Grimberg 
27277d1c127SSebastian Grimberg   @ref User
27377d1c127SSebastian Grimberg **/
2740c73c039SSebastian Grimberg int CeedElemRestrictionRestoreCurlOrientations(CeedElemRestriction rstr, const CeedInt8 **curl_orients) {
27577d1c127SSebastian Grimberg   *curl_orients = NULL;
27677d1c127SSebastian Grimberg   rstr->num_readers--;
277e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2787a982d89SJeremy L. Thompson }
2797a982d89SJeremy L. Thompson 
2807a982d89SJeremy L. Thompson /**
28149fd234cSJeremy L Thompson 
28249fd234cSJeremy L Thompson   @brief Get the E-vector layout of a CeedElemRestriction
28349fd234cSJeremy L Thompson 
284ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
285fcbe8c06SSebastian Grimberg   @param[out] layout  Variable to store layout array, stored as [nodes, components, elements].
286fcbe8c06SSebastian 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]
28749fd234cSJeremy L Thompson 
28849fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
28949fd234cSJeremy L Thompson 
29049fd234cSJeremy L Thompson   @ref Backend
29149fd234cSJeremy L Thompson **/
2922b730f8bSJeremy L Thompson int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, CeedInt (*layout)[3]) {
2936574a04fSJeremy L Thompson   CeedCheck(rstr->layout[0], rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no layout data");
2942b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*layout)[i] = rstr->layout[i];
295e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
29649fd234cSJeremy L Thompson }
29749fd234cSJeremy L Thompson 
29849fd234cSJeremy L Thompson /**
29949fd234cSJeremy L Thompson 
30049fd234cSJeremy L Thompson   @brief Set the E-vector layout of a CeedElemRestriction
30149fd234cSJeremy L Thompson 
302ea61e9acSJeremy L Thompson   @param[in] rstr   CeedElemRestriction
303ea61e9acSJeremy L Thompson   @param[in] layout Variable to containing layout array, stored as [nodes, components, elements].
304ea61e9acSJeremy 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]
30549fd234cSJeremy L Thompson 
30649fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
30749fd234cSJeremy L Thompson 
30849fd234cSJeremy L Thompson   @ref Backend
30949fd234cSJeremy L Thompson **/
3102b730f8bSJeremy L Thompson int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
3112b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) rstr->layout[i] = layout[i];
312e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
31349fd234cSJeremy L Thompson }
31449fd234cSJeremy L Thompson 
31549fd234cSJeremy L Thompson /**
3167a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedElemRestriction
3177a982d89SJeremy L. Thompson 
318ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
3197a982d89SJeremy L. Thompson   @param[out] data Variable to store data
3207a982d89SJeremy L. Thompson 
3217a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3227a982d89SJeremy L. Thompson 
3237a982d89SJeremy L. Thompson   @ref Backend
3247a982d89SJeremy L. Thompson **/
325777ff853SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) {
326777ff853SJeremy L Thompson   *(void **)data = rstr->data;
327e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3287a982d89SJeremy L. Thompson }
3297a982d89SJeremy L. Thompson 
3307a982d89SJeremy L. Thompson /**
3317a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedElemRestriction
3327a982d89SJeremy L. Thompson 
333ea61e9acSJeremy L Thompson   @param[in,out] rstr CeedElemRestriction
334ea61e9acSJeremy L Thompson   @param[in]     data Data to set
3357a982d89SJeremy L. Thompson 
3367a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3377a982d89SJeremy L. Thompson 
3387a982d89SJeremy L. Thompson   @ref Backend
3397a982d89SJeremy L. Thompson **/
340777ff853SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) {
341777ff853SJeremy L Thompson   rstr->data = data;
342e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3437a982d89SJeremy L. Thompson }
3447a982d89SJeremy L. Thompson 
34534359f16Sjeremylt /**
34634359f16Sjeremylt   @brief Increment the reference counter for a CeedElemRestriction
34734359f16Sjeremylt 
348ea61e9acSJeremy L Thompson   @param[in,out] rstr ElemRestriction to increment the reference counter
34934359f16Sjeremylt 
35034359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
35134359f16Sjeremylt 
35234359f16Sjeremylt   @ref Backend
35334359f16Sjeremylt **/
3549560d06aSjeremylt int CeedElemRestrictionReference(CeedElemRestriction rstr) {
35534359f16Sjeremylt   rstr->ref_count++;
35634359f16Sjeremylt   return CEED_ERROR_SUCCESS;
35734359f16Sjeremylt }
35834359f16Sjeremylt 
3596e15d496SJeremy L Thompson /**
3606e15d496SJeremy L Thompson   @brief Estimate number of FLOPs required to apply CeedElemRestriction in t_mode
3616e15d496SJeremy L Thompson 
362ea61e9acSJeremy L Thompson   @param[in]  rstr   ElemRestriction to estimate FLOPs for
363ea61e9acSJeremy L Thompson   @param[in]  t_mode Apply restriction or transpose
364ea61e9acSJeremy L Thompson   @param[out] flops  Address of variable to hold FLOPs estimate
3656e15d496SJeremy L Thompson 
3666e15d496SJeremy L Thompson   @ref Backend
3676e15d496SJeremy L Thompson **/
3682b730f8bSJeremy L Thompson int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedSize *flops) {
36977d1c127SSebastian Grimberg   const bool     *orients      = NULL;
3700c73c039SSebastian Grimberg   const CeedInt8 *curl_orients = NULL;
3712b730f8bSJeremy L Thompson   CeedInt         e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp, scale = 0;
3726e15d496SJeremy L Thompson 
37377d1c127SSebastian Grimberg   CeedCall(CeedElemRestrictionGetOrientations(rstr, CEED_MEM_HOST, &orients));
37477d1c127SSebastian Grimberg   CeedCall(CeedElemRestrictionGetCurlOrientations(rstr, CEED_MEM_HOST, &curl_orients));
37577d1c127SSebastian Grimberg   if (t_mode == CEED_TRANSPOSE) {
37677d1c127SSebastian Grimberg     if (!orients && !curl_orients) {
37777d1c127SSebastian Grimberg       scale = 1;
37877d1c127SSebastian Grimberg     } else if (!curl_orients) {
37977d1c127SSebastian Grimberg       scale = 2;
38077d1c127SSebastian Grimberg     } else {
38177d1c127SSebastian Grimberg       scale = 6;
3826e15d496SJeremy L Thompson     }
38377d1c127SSebastian Grimberg   } else {
38477d1c127SSebastian Grimberg     if (!orients && !curl_orients) {
38577d1c127SSebastian Grimberg       scale = 0;
38677d1c127SSebastian Grimberg     } else if (!curl_orients) {
38777d1c127SSebastian Grimberg       scale = 1;
38877d1c127SSebastian Grimberg     } else {
38977d1c127SSebastian Grimberg       scale = 5;
39077d1c127SSebastian Grimberg     }
39177d1c127SSebastian Grimberg   }
39277d1c127SSebastian Grimberg   CeedCall(CeedElemRestrictionRestoreOrientations(rstr, &orients));
39377d1c127SSebastian Grimberg   CeedCall(CeedElemRestrictionRestoreCurlOrientations(rstr, &curl_orients));
3946e15d496SJeremy L Thompson   *flops = e_size * scale;
3956e15d496SJeremy L Thompson 
3966e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3976e15d496SJeremy L Thompson }
3986e15d496SJeremy L Thompson 
3997a982d89SJeremy L. Thompson /// @}
4007a982d89SJeremy L. Thompson 
40115910d16Sjeremylt /// @cond DOXYGEN_SKIP
40215910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
40315910d16Sjeremylt /// @endcond
40415910d16Sjeremylt 
4057a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
4067a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
4077a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
4087a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
409d7b241e6Sjeremylt /// @{
410d7b241e6Sjeremylt 
4117a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
41245f1e315Sjeremylt const CeedInt CEED_STRIDES_BACKEND[3] = {0};
4137a982d89SJeremy L. Thompson 
4144cc79fe7SJed Brown /// Indicate that no CeedElemRestriction is provided by the user
4152b730f8bSJeremy L Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = &ceed_elemrestriction_none;
4167a982d89SJeremy L. Thompson 
417d7b241e6Sjeremylt /**
418b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
419d7b241e6Sjeremylt 
420ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
421ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array
422ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
423ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
424fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
425fcbe8c06SSebastian 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.
426fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
427fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
428ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
429ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
430fcbe8c06SSebastian Grimberg   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
431fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
432fcbe8c06SSebastian Grimberg 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
433ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
434d7b241e6Sjeremylt 
435b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
436dfdf5a53Sjeremylt 
4377a982d89SJeremy L. Thompson   @ref User
438b11c1e72Sjeremylt **/
4392b730f8bSJeremy L Thompson int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
4402b730f8bSJeremy L Thompson                               CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
4415fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
4425fe0d4faSjeremylt     Ceed delegate;
4436574a04fSJeremy L Thompson 
4442b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
44577d1c127SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
4462b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
447e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
4485fe0d4faSjeremylt   }
4495fe0d4faSjeremylt 
4506574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
4516574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
4526574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
453e022e1f8SJeremy L Thompson 
4542b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
455db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
456d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
457d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
458d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
459d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
460d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
461d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
462d1d35e2fSjeremylt   (*rstr)->num_blk     = num_elem;
463d1d35e2fSjeremylt   (*rstr)->blk_size    = 1;
464*61a27d74SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_STANDARD;
465fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, NULL, *rstr));
466e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
467d7b241e6Sjeremylt }
468d7b241e6Sjeremylt 
469d7b241e6Sjeremylt /**
47077d1c127SSebastian Grimberg   @brief Create a CeedElemRestriction with orientation signs
471fc0567d9Srezgarshakeri 
472ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
473ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array
474ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
475ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
476fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
477fcbe8c06SSebastian 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.
478fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
479fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
480ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
481ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
482fcbe8c06SSebastian Grimberg   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
483fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
484fcbe8c06SSebastian Grimberg 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
48577d1c127SSebastian 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.
486ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
487fc0567d9Srezgarshakeri 
488fc0567d9Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
489fc0567d9Srezgarshakeri 
490fc0567d9Srezgarshakeri   @ref User
491fc0567d9Srezgarshakeri **/
4922b730f8bSJeremy L Thompson int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
49377d1c127SSebastian Grimberg                                       CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orients,
494fc0567d9Srezgarshakeri                                       CeedElemRestriction *rstr) {
495fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreate) {
496fc0567d9Srezgarshakeri     Ceed delegate;
4976574a04fSJeremy L Thompson 
4982b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
499fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
5002b730f8bSJeremy L Thompson     CeedCall(
50177d1c127SSebastian Grimberg         CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, orients, rstr));
502fc0567d9Srezgarshakeri     return CEED_ERROR_SUCCESS;
503fc0567d9Srezgarshakeri   }
504fc0567d9Srezgarshakeri 
5056574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
5066574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
5076574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
508e022e1f8SJeremy L Thompson 
5092b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
510db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
511fc0567d9Srezgarshakeri   (*rstr)->ref_count   = 1;
512fc0567d9Srezgarshakeri   (*rstr)->num_elem    = num_elem;
513fc0567d9Srezgarshakeri   (*rstr)->elem_size   = elem_size;
514fc0567d9Srezgarshakeri   (*rstr)->num_comp    = num_comp;
515fc0567d9Srezgarshakeri   (*rstr)->comp_stride = comp_stride;
516fc0567d9Srezgarshakeri   (*rstr)->l_size      = l_size;
517fc0567d9Srezgarshakeri   (*rstr)->num_blk     = num_elem;
518fc0567d9Srezgarshakeri   (*rstr)->blk_size    = 1;
519fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_ORIENTED;
520fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, orients, NULL, *rstr));
52177d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
52277d1c127SSebastian Grimberg }
52377d1c127SSebastian Grimberg 
52477d1c127SSebastian Grimberg /**
52577d1c127SSebastian Grimberg   @brief Create a CeedElemRestriction with a general tridiagonal transformation matrix for curl-conforming elements
52677d1c127SSebastian Grimberg 
52777d1c127SSebastian Grimberg   @param[in]  ceed         Ceed object where the CeedElemRestriction will be created
52877d1c127SSebastian Grimberg   @param[in]  num_elem     Number of elements described in the @a offsets array
52977d1c127SSebastian Grimberg   @param[in]  elem_size    Size (number of "nodes") per element
53077d1c127SSebastian Grimberg   @param[in]  num_comp     Number of field components per interpolation node (1 for scalar fields)
531fcbe8c06SSebastian Grimberg   @param[in]  comp_stride  Stride between components for the same L-vector "node".
532fcbe8c06SSebastian 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.
533fcbe8c06SSebastian Grimberg   @param[in]  l_size       The size of the L-vector.
534fcbe8c06SSebastian Grimberg                              This vector may be larger than the elements and fields given by this restriction.
53577d1c127SSebastian Grimberg   @param[in]  mem_type     Memory type of the @a offsets array, see CeedMemType
53677d1c127SSebastian Grimberg   @param[in]  copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
537fcbe8c06SSebastian Grimberg   @param[in]  offsets      Array of shape [@a num_elem, @a elem_size].
538fcbe8c06SSebastian Grimberg                              Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i,
539fcbe8c06SSebastian Grimberg where 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
5407c1dbaffSSebastian 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]
5417c1dbaffSSebastian 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
5427c1dbaffSSebastian 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,
5437c1dbaffSSebastian Grimberg which is a way to resolve face orientation issues for 3D meshes (https://dl.acm.org/doi/pdf/10.1145/3524456).
54477d1c127SSebastian Grimberg   @param[out] rstr         Address of the variable where the newly created CeedElemRestriction will be stored
54577d1c127SSebastian Grimberg 
54677d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
54777d1c127SSebastian Grimberg 
54877d1c127SSebastian Grimberg   @ref User
54977d1c127SSebastian Grimberg **/
55077d1c127SSebastian Grimberg int CeedElemRestrictionCreateCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
5510c73c039SSebastian Grimberg                                           CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const CeedInt8 *curl_orients,
55277d1c127SSebastian Grimberg                                           CeedElemRestriction *rstr) {
553fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreate) {
55477d1c127SSebastian Grimberg     Ceed delegate;
55577d1c127SSebastian Grimberg 
55677d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
557fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
55877d1c127SSebastian Grimberg     CeedCall(CeedElemRestrictionCreateCurlOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
55977d1c127SSebastian Grimberg                                                    curl_orients, rstr));
56077d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
56177d1c127SSebastian Grimberg   }
56277d1c127SSebastian Grimberg 
56377d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
56477d1c127SSebastian Grimberg   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
56577d1c127SSebastian Grimberg   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
56677d1c127SSebastian Grimberg 
56777d1c127SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
568fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
56977d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
57077d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
57177d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
57277d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
57377d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
57477d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
57577d1c127SSebastian Grimberg   (*rstr)->num_blk     = num_elem;
57677d1c127SSebastian Grimberg   (*rstr)->blk_size    = 1;
577fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_CURL_ORIENTED;
578fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, curl_orients, *rstr));
579fc0567d9Srezgarshakeri   return CEED_ERROR_SUCCESS;
580fc0567d9Srezgarshakeri }
581fc0567d9Srezgarshakeri 
582fc0567d9Srezgarshakeri /**
5837509a596Sjeremylt   @brief Create a strided CeedElemRestriction
584d7b241e6Sjeremylt 
585ea61e9acSJeremy L Thompson   @param[in]  ceed      Ceed object where the CeedElemRestriction will be created
586ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
587ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
588ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation "node" (1 for scalar fields)
589fcbe8c06SSebastian Grimberg   @param[in]  l_size    The size of the L-vector.
590fcbe8c06SSebastian Grimberg                           This vector may be larger than the elements and fields given by this restriction.
591fcbe8c06SSebastian Grimberg   @param[in]  strides   Array for strides between [nodes, components, elements].
592fcbe8c06SSebastian 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].
593fcbe8c06SSebastian Grimberg                           @a CEED_STRIDES_BACKEND may be used with vectors created by a Ceed backend.
594ea61e9acSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created CeedElemRestriction will be stored
595d7b241e6Sjeremylt 
596b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
597dfdf5a53Sjeremylt 
5987a982d89SJeremy L. Thompson   @ref User
599b11c1e72Sjeremylt **/
6002b730f8bSJeremy L Thompson int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedSize l_size, const CeedInt strides[3],
601f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
6025fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
6035fe0d4faSjeremylt     Ceed delegate;
604b04eb3d9SSebastian Grimberg 
6052b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
606fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
6072b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, l_size, strides, rstr));
608e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6095fe0d4faSjeremylt   }
6105fe0d4faSjeremylt 
6116574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
6126574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
613e022e1f8SJeremy L Thompson 
6142b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
615db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
616d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
617d1d35e2fSjeremylt   (*rstr)->num_elem  = num_elem;
618d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
619d1d35e2fSjeremylt   (*rstr)->num_comp  = num_comp;
620d1d35e2fSjeremylt   (*rstr)->l_size    = l_size;
621d1d35e2fSjeremylt   (*rstr)->num_blk   = num_elem;
622d1d35e2fSjeremylt   (*rstr)->blk_size  = 1;
623fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type = CEED_RESTRICTION_STRIDED;
6242b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
6252b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
626fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
627e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
628d7b241e6Sjeremylt }
629d7b241e6Sjeremylt 
630d7b241e6Sjeremylt /**
631b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
632d7b241e6Sjeremylt 
633ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created.
634ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array.
635ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of unknowns) per element
636ea61e9acSJeremy L Thompson   @param[in]  blk_size    Number of elements in a block
637ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
638fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
639fcbe8c06SSebastian 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.
640fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
641fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
642ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
643ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
644fcbe8c06SSebastian Grimberg   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
645fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
646fcbe8c06SSebastian 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
647fcbe8c06SSebastian Grimberg  the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
648ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
649d7b241e6Sjeremylt 
650b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
651dfdf5a53Sjeremylt 
6527a982d89SJeremy L. Thompson   @ref Backend
653b11c1e72Sjeremylt  **/
6542b730f8bSJeremy L Thompson int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedInt comp_stride,
6552b730f8bSJeremy L Thompson                                      CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets,
6564ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
657d1d35e2fSjeremylt   CeedInt *blk_offsets;
658d1d35e2fSjeremylt   CeedInt  num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
659d7b241e6Sjeremylt 
6605fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
6615fe0d4faSjeremylt     Ceed delegate;
6626574a04fSJeremy L Thompson 
6632b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
6646402da51SJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
6652b730f8bSJeremy L Thompson     CeedCall(
6662b730f8bSJeremy L Thompson         CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, blk_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
667e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6685fe0d4faSjeremylt   }
669d7b241e6Sjeremylt 
6706574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
6716574a04fSJeremy L Thompson   CeedCheck(blk_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
6726574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
6736574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
674e022e1f8SJeremy L Thompson 
6752b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(num_blk * blk_size * elem_size, &blk_offsets));
6762b730f8bSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size, elem_size));
677d7b241e6Sjeremylt 
678db002c03SJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
679db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
680d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
681d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
682d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
683d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
684d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
685d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
686d1d35e2fSjeremylt   (*rstr)->num_blk     = num_blk;
687d1d35e2fSjeremylt   (*rstr)->blk_size    = blk_size;
688*61a27d74SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_STANDARD;
689fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)blk_offsets, NULL, NULL, *rstr));
690d1d35e2fSjeremylt   if (copy_mode == CEED_OWN_POINTER) {
6912b730f8bSJeremy L Thompson     CeedCall(CeedFree(&offsets));
6921d102b48SJeremy L Thompson   }
693e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
694d7b241e6Sjeremylt }
695d7b241e6Sjeremylt 
696b11c1e72Sjeremylt /**
69777d1c127SSebastian Grimberg   @brief Create a blocked oriented CeedElemRestriction, typically only called by backends
69877d1c127SSebastian Grimberg 
69977d1c127SSebastian Grimberg   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created.
70077d1c127SSebastian Grimberg   @param[in]  num_elem    Number of elements described in the @a offsets array.
70177d1c127SSebastian Grimberg   @param[in]  elem_size   Size (number of unknowns) per element
70277d1c127SSebastian Grimberg   @param[in]  blk_size    Number of elements in a block
70377d1c127SSebastian Grimberg   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
704fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
705fcbe8c06SSebastian 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.
706fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
707fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
70877d1c127SSebastian Grimberg   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
70977d1c127SSebastian Grimberg   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
710fcbe8c06SSebastian Grimberg   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
711fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
712fcbe8c06SSebastian 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
713fcbe8c06SSebastian Grimberg  the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
714fcbe8c06SSebastian 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.
715fcbe8c06SSebastian Grimberg                             Will also be permuted and padded similarly to @a offsets.
71677d1c127SSebastian Grimberg   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
71777d1c127SSebastian Grimberg 
71877d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
71977d1c127SSebastian Grimberg 
72077d1c127SSebastian Grimberg   @ref Backend
72177d1c127SSebastian Grimberg  **/
72277d1c127SSebastian Grimberg int CeedElemRestrictionCreateBlockedOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedInt comp_stride,
72377d1c127SSebastian Grimberg                                              CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets,
72477d1c127SSebastian Grimberg                                              const bool *orients, CeedElemRestriction *rstr) {
72577d1c127SSebastian Grimberg   CeedInt *blk_offsets;
72677d1c127SSebastian Grimberg   bool    *blk_orients;
72777d1c127SSebastian Grimberg   CeedInt  num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
72877d1c127SSebastian Grimberg 
729fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreateBlocked) {
73077d1c127SSebastian Grimberg     Ceed delegate;
73177d1c127SSebastian Grimberg 
73277d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
733fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
73477d1c127SSebastian Grimberg     CeedCall(CeedElemRestrictionCreateBlockedOriented(delegate, num_elem, elem_size, blk_size, num_comp, comp_stride, l_size, mem_type, copy_mode,
73577d1c127SSebastian Grimberg                                                       offsets, orients, rstr));
73677d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
73777d1c127SSebastian Grimberg   }
73877d1c127SSebastian Grimberg 
73977d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
74077d1c127SSebastian Grimberg   CeedCheck(blk_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
74177d1c127SSebastian Grimberg   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
74277d1c127SSebastian Grimberg   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
74377d1c127SSebastian Grimberg 
74477d1c127SSebastian Grimberg   CeedCall(CeedCalloc(num_blk * blk_size * elem_size, &blk_offsets));
74577d1c127SSebastian Grimberg   CeedCall(CeedCalloc(num_blk * blk_size * elem_size, &blk_orients));
74677d1c127SSebastian Grimberg   CeedCall(CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size, elem_size));
7470c73c039SSebastian Grimberg   CeedCall(CeedPermutePadOrients(orients, blk_orients, num_blk, num_elem, blk_size, elem_size));
74877d1c127SSebastian Grimberg 
749fcbe8c06SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
750fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
75177d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
75277d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
75377d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
75477d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
75577d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
75677d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
75777d1c127SSebastian Grimberg   (*rstr)->num_blk     = num_blk;
75877d1c127SSebastian Grimberg   (*rstr)->blk_size    = blk_size;
759fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_ORIENTED;
760fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)blk_offsets, (const bool *)blk_orients, NULL, *rstr));
76177d1c127SSebastian Grimberg   if (copy_mode == CEED_OWN_POINTER) {
76277d1c127SSebastian Grimberg     CeedCall(CeedFree(&offsets));
76377d1c127SSebastian Grimberg   }
76477d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
76577d1c127SSebastian Grimberg }
76677d1c127SSebastian Grimberg 
76777d1c127SSebastian Grimberg /**
76877d1c127SSebastian Grimberg   @brief Create a blocked curl-oriented CeedElemRestriction, typically only called by backends
76977d1c127SSebastian Grimberg 
77077d1c127SSebastian Grimberg   @param[in]  ceed         Ceed object where the CeedElemRestriction will be created.
77177d1c127SSebastian Grimberg   @param[in]  num_elem     Number of elements described in the @a offsets array.
77277d1c127SSebastian Grimberg   @param[in]  elem_size    Size (number of unknowns) per element
77377d1c127SSebastian Grimberg   @param[in]  blk_size     Number of elements in a block
77477d1c127SSebastian Grimberg   @param[in]  num_comp     Number of field components per interpolation node (1 for scalar fields)
775fcbe8c06SSebastian Grimberg   @param[in]  comp_stride  Stride between components for the same L-vector "node".
776fcbe8c06SSebastian 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.
777fcbe8c06SSebastian Grimberg   @param[in]  l_size       The size of the L-vector.
778fcbe8c06SSebastian Grimberg                              This vector may be larger than the elements and fields given by this restriction.
77977d1c127SSebastian Grimberg   @param[in]  mem_type     Memory type of the @a offsets array, see CeedMemType
78077d1c127SSebastian Grimberg   @param[in]  copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
781fcbe8c06SSebastian Grimberg   @param[in]  offsets      Array of shape [@a num_elem, @a elem_size].
782fcbe8c06SSebastian Grimberg                              Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i,
783fcbe8c06SSebastian 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
784fcbe8c06SSebastian Grimberg for the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
7857c1dbaffSSebastian 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]
7867c1dbaffSSebastian 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
7877c1dbaffSSebastian 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,
7887c1dbaffSSebastian 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
7897c1dbaffSSebastian Grimberg similarly to @a offsets.
79077d1c127SSebastian Grimberg   @param[out] rstr         Address of the variable where the newly created CeedElemRestriction will be stored
79177d1c127SSebastian Grimberg 
79277d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
79377d1c127SSebastian Grimberg 
79477d1c127SSebastian Grimberg   @ref Backend
79577d1c127SSebastian Grimberg  **/
79677d1c127SSebastian Grimberg int CeedElemRestrictionCreateBlockedCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp,
79777d1c127SSebastian Grimberg                                                  CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode,
7980c73c039SSebastian Grimberg                                                  const CeedInt *offsets, const CeedInt8 *curl_orients, CeedElemRestriction *rstr) {
79977d1c127SSebastian Grimberg   CeedInt  *blk_offsets;
8000c73c039SSebastian Grimberg   CeedInt8 *blk_curl_orients;
80177d1c127SSebastian Grimberg   CeedInt   num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
80277d1c127SSebastian Grimberg 
803fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreateBlocked) {
80477d1c127SSebastian Grimberg     Ceed delegate;
80577d1c127SSebastian Grimberg 
80677d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
807fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
80877d1c127SSebastian Grimberg     CeedCall(CeedElemRestrictionCreateBlockedCurlOriented(delegate, num_elem, elem_size, blk_size, num_comp, comp_stride, l_size, mem_type, copy_mode,
80977d1c127SSebastian Grimberg                                                           offsets, curl_orients, rstr));
81077d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
81177d1c127SSebastian Grimberg   }
81277d1c127SSebastian Grimberg 
81377d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
81477d1c127SSebastian Grimberg   CeedCheck(blk_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
81577d1c127SSebastian Grimberg   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
81677d1c127SSebastian Grimberg   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
81777d1c127SSebastian Grimberg 
81877d1c127SSebastian Grimberg   CeedCall(CeedCalloc(num_blk * blk_size * elem_size, &blk_offsets));
81977d1c127SSebastian Grimberg   CeedCall(CeedCalloc(num_blk * blk_size * 3 * elem_size, &blk_curl_orients));
82077d1c127SSebastian Grimberg   CeedCall(CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size, elem_size));
8210c73c039SSebastian Grimberg   CeedCall(CeedPermutePadCurlOrients(curl_orients, blk_curl_orients, num_blk, num_elem, blk_size, 3 * elem_size));
82277d1c127SSebastian Grimberg 
823fcbe8c06SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
824fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
82577d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
82677d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
82777d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
82877d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
82977d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
83077d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
83177d1c127SSebastian Grimberg   (*rstr)->num_blk     = num_blk;
83277d1c127SSebastian Grimberg   (*rstr)->blk_size    = blk_size;
833fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_CURL_ORIENTED;
8340c73c039SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)blk_offsets, NULL, (const CeedInt8 *)blk_curl_orients,
835fcbe8c06SSebastian Grimberg                                               *rstr));
83677d1c127SSebastian Grimberg   if (copy_mode == CEED_OWN_POINTER) {
83777d1c127SSebastian Grimberg     CeedCall(CeedFree(&offsets));
83877d1c127SSebastian Grimberg   }
83977d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
84077d1c127SSebastian Grimberg }
84177d1c127SSebastian Grimberg 
84277d1c127SSebastian Grimberg /**
84377d1c127SSebastian Grimberg   @brief Create a blocked strided CeedElemRestriction, typically only called by backends
8447509a596Sjeremylt 
845ea61e9acSJeremy L Thompson   @param[in]  ceed      Ceed object where the CeedElemRestriction will be created
846ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
847ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
848ea61e9acSJeremy L Thompson   @param[in]  blk_size  Number of elements in a block
849ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation node (1 for scalar fields)
850fcbe8c06SSebastian Grimberg   @param[in]  l_size    The size of the L-vector.
851fcbe8c06SSebastian Grimberg                           This vector may be larger than the elements and fields given by this restriction.
852fcbe8c06SSebastian Grimberg   @param[in]  strides   Array for strides between [nodes, components, elements].
853fcbe8c06SSebastian 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].
854fcbe8c06SSebastian Grimberg                           @a CEED_STRIDES_BACKEND may be used with vectors created by a Ceed backend.
855ea61e9acSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created CeedElemRestriction will be stored
8567509a596Sjeremylt 
8577509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
8587509a596Sjeremylt 
8597a982d89SJeremy L. Thompson   @ref User
8607509a596Sjeremylt **/
8612b730f8bSJeremy L Thompson int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedSize l_size,
8628621c6c6SJeremy L Thompson                                             const CeedInt strides[3], CeedElemRestriction *rstr) {
863d1d35e2fSjeremylt   CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
8647509a596Sjeremylt 
8657509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
8667509a596Sjeremylt     Ceed delegate;
8676574a04fSJeremy L Thompson 
8682b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
869fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
8702b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, blk_size, num_comp, l_size, strides, rstr));
871e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
8727509a596Sjeremylt   }
8737509a596Sjeremylt 
8746574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
8756574a04fSJeremy L Thompson   CeedCheck(blk_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
8766574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
877e022e1f8SJeremy L Thompson 
8782b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
879db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
880d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
881d1d35e2fSjeremylt   (*rstr)->num_elem  = num_elem;
882d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
883d1d35e2fSjeremylt   (*rstr)->num_comp  = num_comp;
884d1d35e2fSjeremylt   (*rstr)->l_size    = l_size;
885d1d35e2fSjeremylt   (*rstr)->num_blk   = num_blk;
886d1d35e2fSjeremylt   (*rstr)->blk_size  = blk_size;
887fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type = CEED_RESTRICTION_STRIDED;
8882b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
8892b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
890fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
891e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
8927509a596Sjeremylt }
8937509a596Sjeremylt 
8947509a596Sjeremylt /**
8957c1dbaffSSebastian Grimberg   @brief Copy the pointer to a CeedElemRestriction and set `CeedElemRestrictionApply()` implementation to use the unsigned version.
896c17ec2beSJeremy L Thompson 
897c17ec2beSJeremy L Thompson   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
898c17ec2beSJeremy L Thompson 
899c17ec2beSJeremy L Thompson   @param[in]     rstr          CeedElemRestriction to create unsigned reference to
900c17ec2beSJeremy L Thompson   @param[in,out] rstr_unsigned Variable to store unsigned CeedElemRestriction
901c17ec2beSJeremy L Thompson 
902c17ec2beSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
903c17ec2beSJeremy L Thompson 
904c17ec2beSJeremy L Thompson   @ref User
905c17ec2beSJeremy L Thompson **/
906c17ec2beSJeremy L Thompson int CeedElemRestrictionCreateUnsignedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unsigned) {
907c17ec2beSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr_unsigned));
908c17ec2beSJeremy L Thompson 
909c17ec2beSJeremy L Thompson   // Copy old rstr
910c17ec2beSJeremy L Thompson   memcpy(*rstr_unsigned, rstr, sizeof(struct CeedElemRestriction_private));
911c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ceed = NULL;
912c17ec2beSJeremy L Thompson   CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unsigned)->ceed));
913c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ref_count = 1;
914c17ec2beSJeremy L Thompson   (*rstr_unsigned)->strides   = NULL;
915c17ec2beSJeremy L Thompson   if (rstr->strides) {
916c17ec2beSJeremy L Thompson     CeedCall(CeedMalloc(3, &(*rstr_unsigned)->strides));
917c17ec2beSJeremy L Thompson     for (CeedInt i = 0; i < 3; i++) (*rstr_unsigned)->strides[i] = rstr->strides[i];
918c17ec2beSJeremy L Thompson   }
9197c1dbaffSSebastian Grimberg   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unsigned)->rstr_base));
920c17ec2beSJeremy L Thompson 
921c17ec2beSJeremy L Thompson   // Override Apply
922c17ec2beSJeremy L Thompson   (*rstr_unsigned)->Apply = rstr->ApplyUnsigned;
923c17ec2beSJeremy L Thompson 
924c17ec2beSJeremy L Thompson   return CEED_ERROR_SUCCESS;
925c17ec2beSJeremy L Thompson }
926c17ec2beSJeremy L Thompson 
927c17ec2beSJeremy L Thompson /**
9287c1dbaffSSebastian Grimberg   @brief Copy the pointer to a CeedElemRestriction and set `CeedElemRestrictionApply()` implementation to use the unoriented version.
9297c1dbaffSSebastian Grimberg 
9307c1dbaffSSebastian Grimberg   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
9317c1dbaffSSebastian Grimberg 
9327c1dbaffSSebastian Grimberg   @param[in]     rstr            CeedElemRestriction to create unoriented reference to
9337c1dbaffSSebastian Grimberg   @param[in,out] rstr_unoriented Variable to store unoriented CeedElemRestriction
9347c1dbaffSSebastian Grimberg 
9357c1dbaffSSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
9367c1dbaffSSebastian Grimberg 
9377c1dbaffSSebastian Grimberg   @ref User
9387c1dbaffSSebastian Grimberg **/
9397c1dbaffSSebastian Grimberg int CeedElemRestrictionCreateUnorientedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unoriented) {
9407c1dbaffSSebastian Grimberg   CeedCall(CeedCalloc(1, rstr_unoriented));
9417c1dbaffSSebastian Grimberg 
9427c1dbaffSSebastian Grimberg   // Copy old rstr
9437c1dbaffSSebastian Grimberg   memcpy(*rstr_unoriented, rstr, sizeof(struct CeedElemRestriction_private));
9447c1dbaffSSebastian Grimberg   (*rstr_unoriented)->ceed = NULL;
9457c1dbaffSSebastian Grimberg   CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unoriented)->ceed));
9467c1dbaffSSebastian Grimberg   (*rstr_unoriented)->ref_count = 1;
9477c1dbaffSSebastian Grimberg   (*rstr_unoriented)->strides   = NULL;
9487c1dbaffSSebastian Grimberg   if (rstr->strides) {
9497c1dbaffSSebastian Grimberg     CeedCall(CeedMalloc(3, &(*rstr_unoriented)->strides));
9507c1dbaffSSebastian Grimberg     for (CeedInt i = 0; i < 3; i++) (*rstr_unoriented)->strides[i] = rstr->strides[i];
9517c1dbaffSSebastian Grimberg   }
9527c1dbaffSSebastian Grimberg   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unoriented)->rstr_base));
9537c1dbaffSSebastian Grimberg 
9547c1dbaffSSebastian Grimberg   // Override Apply
9557c1dbaffSSebastian Grimberg   (*rstr_unoriented)->Apply = rstr->ApplyUnoriented;
9567c1dbaffSSebastian Grimberg 
9577c1dbaffSSebastian Grimberg   return CEED_ERROR_SUCCESS;
9587c1dbaffSSebastian Grimberg }
9597c1dbaffSSebastian Grimberg 
9607c1dbaffSSebastian Grimberg /**
961ea61e9acSJeremy L Thompson   @brief Copy the pointer to a CeedElemRestriction.
9629fd66db6SSebastian Grimberg 
963ea61e9acSJeremy L Thompson   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
9649560d06aSjeremylt 
9659fd66db6SSebastian 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.
9669fd66db6SSebastian Grimberg         This CeedElemRestriction will be destroyed if `rstr_copy` is the only reference to this CeedElemRestriction.
967ea61e9acSJeremy L Thompson 
968ea61e9acSJeremy L Thompson   @param[in]     rstr      CeedElemRestriction to copy reference to
969ea61e9acSJeremy L Thompson   @param[in,out] rstr_copy Variable to store copied reference
9709560d06aSjeremylt 
9719560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
9729560d06aSjeremylt 
9739560d06aSjeremylt   @ref User
9749560d06aSjeremylt **/
9752b730f8bSJeremy L Thompson int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_copy) {
976393ac2cdSJeremy L Thompson   if (rstr != CEED_ELEMRESTRICTION_NONE) CeedCall(CeedElemRestrictionReference(rstr));
9772b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionDestroy(rstr_copy));
9789560d06aSjeremylt   *rstr_copy = rstr;
9799560d06aSjeremylt   return CEED_ERROR_SUCCESS;
9809560d06aSjeremylt }
9819560d06aSjeremylt 
9829560d06aSjeremylt /**
983b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
984b11c1e72Sjeremylt 
985ea61e9acSJeremy L Thompson   @param[in]  rstr  CeedElemRestriction
986ea61e9acSJeremy L Thompson   @param[out] l_vec The address of the L-vector to be created, or NULL
987ea61e9acSJeremy L Thompson   @param[out] e_vec The address of the E-vector to be created, or NULL
988b11c1e72Sjeremylt 
989b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
990dfdf5a53Sjeremylt 
9917a982d89SJeremy L. Thompson   @ref User
992b11c1e72Sjeremylt **/
9932b730f8bSJeremy L Thompson int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, CeedVector *e_vec) {
994d2643443SJeremy L Thompson   CeedSize e_size, l_size;
995d1d35e2fSjeremylt   l_size = rstr->l_size;
996d1d35e2fSjeremylt   e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
9972b730f8bSJeremy L Thompson   if (l_vec) CeedCall(CeedVectorCreate(rstr->ceed, l_size, l_vec));
9982b730f8bSJeremy L Thompson   if (e_vec) CeedCall(CeedVectorCreate(rstr->ceed, e_size, e_vec));
999e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1000d7b241e6Sjeremylt }
1001d7b241e6Sjeremylt 
1002d7b241e6Sjeremylt /**
1003d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
1004d7b241e6Sjeremylt 
1005ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
1006ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1007ea61e9acSJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
1008fcbe8c06SSebastian Grimberg   @param[out] ru      Output vector (of shape [@a num_elem * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
1009fcbe8c06SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
1010ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
1011b11c1e72Sjeremylt 
1012b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1013dfdf5a53Sjeremylt 
10147a982d89SJeremy L. Thompson   @ref User
1015b11c1e72Sjeremylt **/
10162b730f8bSJeremy L Thompson int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
1017d7b241e6Sjeremylt   CeedInt m, n;
1018d7b241e6Sjeremylt 
1019d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
1020d1d35e2fSjeremylt     m = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
1021d1d35e2fSjeremylt     n = rstr->l_size;
1022d7b241e6Sjeremylt   } else {
1023d1d35e2fSjeremylt     m = rstr->l_size;
1024d1d35e2fSjeremylt     n = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
1025d7b241e6Sjeremylt   }
10266574a04fSJeremy L Thompson   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
10276574a04fSJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
10286574a04fSJeremy L Thompson   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
10296574a04fSJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
10302b730f8bSJeremy L Thompson   if (rstr->num_elem > 0) CeedCall(rstr->Apply(rstr, t_mode, u, ru, request));
1031e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1032d7b241e6Sjeremylt }
1033d7b241e6Sjeremylt 
1034d7b241e6Sjeremylt /**
1035d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
1036be9261b7Sjeremylt 
1037ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
1038ea61e9acSJeremy L Thompson   @param[in]  block   Block number to restrict to/from, i.e. block=0 will handle elements [0 : blk_size] and block=3 will handle elements [3*blk_size
1039ea61e9acSJeremy L Thompson : 4*blk_size]
1040ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1041ea61e9acSJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
1042fcbe8c06SSebastian Grimberg   @param[out] ru      Output vector (of shape [@a blk_size * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
1043fcbe8c06SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
1044ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
1045be9261b7Sjeremylt 
1046be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
1047be9261b7Sjeremylt 
10487a982d89SJeremy L. Thompson   @ref Backend
1049be9261b7Sjeremylt **/
10502b730f8bSJeremy L Thompson int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
10512b730f8bSJeremy L Thompson                                   CeedRequest *request) {
1052be9261b7Sjeremylt   CeedInt m, n;
1053be9261b7Sjeremylt 
10546402da51SJeremy L Thompson   CeedCheck(rstr->ApplyBlock, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionApplyBlock");
10556402da51SJeremy L Thompson 
1056d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
1057d1d35e2fSjeremylt     m = rstr->blk_size * rstr->elem_size * rstr->num_comp;
1058d1d35e2fSjeremylt     n = rstr->l_size;
1059be9261b7Sjeremylt   } else {
1060d1d35e2fSjeremylt     m = rstr->l_size;
1061d1d35e2fSjeremylt     n = rstr->blk_size * rstr->elem_size * rstr->num_comp;
1062be9261b7Sjeremylt   }
10636574a04fSJeremy L Thompson   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
10646574a04fSJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
10656574a04fSJeremy L Thompson   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
10666574a04fSJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
10676574a04fSJeremy L Thompson   CeedCheck(rstr->blk_size * block <= rstr->num_elem, rstr->ceed, CEED_ERROR_DIMENSION,
10686574a04fSJeremy L Thompson             "Cannot retrieve block %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", block, rstr->blk_size * block,
10696574a04fSJeremy L Thompson             rstr->num_elem);
10702b730f8bSJeremy L Thompson   CeedCall(rstr->ApplyBlock(rstr, block, t_mode, u, ru, request));
1071e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1072be9261b7Sjeremylt }
1073be9261b7Sjeremylt 
1074be9261b7Sjeremylt /**
1075b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedElemRestriction
1076b7c9bbdaSJeremy L Thompson 
1077ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
1078b7c9bbdaSJeremy L Thompson   @param[out] ceed Variable to store Ceed
1079b7c9bbdaSJeremy L Thompson 
1080b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1081b7c9bbdaSJeremy L Thompson 
1082b7c9bbdaSJeremy L Thompson   @ref Advanced
1083b7c9bbdaSJeremy L Thompson **/
1084b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
1085b7c9bbdaSJeremy L Thompson   *ceed = rstr->ceed;
1086b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1087b7c9bbdaSJeremy L Thompson }
1088b7c9bbdaSJeremy L Thompson 
1089b7c9bbdaSJeremy L Thompson /**
1090d979a051Sjeremylt   @brief Get the L-vector component stride
1091a681ae63Sjeremylt 
1092ea61e9acSJeremy L Thompson   @param[in]  rstr        CeedElemRestriction
1093d1d35e2fSjeremylt   @param[out] comp_stride Variable to store component stride
1094a681ae63Sjeremylt 
1095a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1096a681ae63Sjeremylt 
1097b7c9bbdaSJeremy L Thompson   @ref Advanced
1098a681ae63Sjeremylt **/
10992b730f8bSJeremy L Thompson int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, CeedInt *comp_stride) {
1100d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
1101e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1102a681ae63Sjeremylt }
1103a681ae63Sjeremylt 
1104a681ae63Sjeremylt /**
1105a681ae63Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
1106a681ae63Sjeremylt 
1107ea61e9acSJeremy L Thompson   @param[in] rstr      CeedElemRestriction
1108d1d35e2fSjeremylt   @param[out] num_elem Variable to store number of elements
1109a681ae63Sjeremylt 
1110a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1111a681ae63Sjeremylt 
1112b7c9bbdaSJeremy L Thompson   @ref Advanced
1113a681ae63Sjeremylt **/
11142b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, CeedInt *num_elem) {
1115d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
1116e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1117a681ae63Sjeremylt }
1118a681ae63Sjeremylt 
1119a681ae63Sjeremylt /**
1120a681ae63Sjeremylt   @brief Get the size of elements in the CeedElemRestriction
1121a681ae63Sjeremylt 
1122ea61e9acSJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
1123d1d35e2fSjeremylt   @param[out] elem_size Variable to store size of elements
1124a681ae63Sjeremylt 
1125a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1126a681ae63Sjeremylt 
1127b7c9bbdaSJeremy L Thompson   @ref Advanced
1128a681ae63Sjeremylt **/
11292b730f8bSJeremy L Thompson int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, CeedInt *elem_size) {
1130d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
1131e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1132a681ae63Sjeremylt }
1133a681ae63Sjeremylt 
1134a681ae63Sjeremylt /**
1135d979a051Sjeremylt   @brief Get the size of the l-vector for a CeedElemRestriction
1136a681ae63Sjeremylt 
1137ea61e9acSJeremy L Thompson   @param[in]  rstr   CeedElemRestriction
1138d1d35e2fSjeremylt   @param[out] l_size Variable to store number of nodes
1139a681ae63Sjeremylt 
1140a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1141a681ae63Sjeremylt 
1142b7c9bbdaSJeremy L Thompson   @ref Advanced
1143a681ae63Sjeremylt **/
11442b730f8bSJeremy L Thompson int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, CeedSize *l_size) {
1145d1d35e2fSjeremylt   *l_size = rstr->l_size;
1146e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1147a681ae63Sjeremylt }
1148a681ae63Sjeremylt 
1149a681ae63Sjeremylt /**
1150ea61e9acSJeremy L Thompson   @brief Get the number of components in the elements of a CeedElemRestriction
1151a681ae63Sjeremylt 
1152ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction
1153d1d35e2fSjeremylt   @param[out] num_comp Variable to store number of components
1154a681ae63Sjeremylt 
1155a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1156a681ae63Sjeremylt 
1157b7c9bbdaSJeremy L Thompson   @ref Advanced
1158a681ae63Sjeremylt **/
11592b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, CeedInt *num_comp) {
1160d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
1161e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1162a681ae63Sjeremylt }
1163a681ae63Sjeremylt 
1164a681ae63Sjeremylt /**
1165a681ae63Sjeremylt   @brief Get the number of blocks in a CeedElemRestriction
1166a681ae63Sjeremylt 
1167ea61e9acSJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
1168d1d35e2fSjeremylt   @param[out] num_block Variable to store number of blocks
1169a681ae63Sjeremylt 
1170a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1171a681ae63Sjeremylt 
1172b7c9bbdaSJeremy L Thompson   @ref Advanced
1173a681ae63Sjeremylt **/
11742b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, CeedInt *num_block) {
1175d1d35e2fSjeremylt   *num_block = rstr->num_blk;
1176e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1177a681ae63Sjeremylt }
1178a681ae63Sjeremylt 
1179a681ae63Sjeremylt /**
1180a681ae63Sjeremylt   @brief Get the size of blocks in the CeedElemRestriction
1181a681ae63Sjeremylt 
1182ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction
1183d1d35e2fSjeremylt   @param[out] blk_size Variable to store size of blocks
1184a681ae63Sjeremylt 
1185a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1186a681ae63Sjeremylt 
1187b7c9bbdaSJeremy L Thompson   @ref Advanced
1188a681ae63Sjeremylt **/
11892b730f8bSJeremy L Thompson int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, CeedInt *blk_size) {
1190d1d35e2fSjeremylt   *blk_size = rstr->blk_size;
1191e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1192a681ae63Sjeremylt }
1193a681ae63Sjeremylt 
1194a681ae63Sjeremylt /**
1195d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
11961469ee4dSjeremylt 
1197ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
1198d1d35e2fSjeremylt   @param[out] mult Vector to store multiplicity (of size l_size)
11991469ee4dSjeremylt 
12001469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
12011469ee4dSjeremylt 
12027a982d89SJeremy L. Thompson   @ref User
12031469ee4dSjeremylt **/
12042b730f8bSJeremy L Thompson int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, CeedVector mult) {
1205d1d35e2fSjeremylt   CeedVector e_vec;
12061469ee4dSjeremylt 
120725509ebbSRezgar Shakeri   // Create e_vec to hold intermediate computation in E^T (E 1)
12082b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionCreateVector(rstr, NULL, &e_vec));
12091469ee4dSjeremylt 
121025509ebbSRezgar Shakeri   // Compute e_vec = E * 1
12112b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 1.0));
12122b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, CEED_REQUEST_IMMEDIATE));
121325509ebbSRezgar Shakeri   // Compute multiplicity, mult = E^T * e_vec = E^T (E 1)
12142b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 0.0));
12152b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, CEED_REQUEST_IMMEDIATE));
12161469ee4dSjeremylt   // Cleanup
12172b730f8bSJeremy L Thompson   CeedCall(CeedVectorDestroy(&e_vec));
1218e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
12191469ee4dSjeremylt }
12201469ee4dSjeremylt 
12211469ee4dSjeremylt /**
1222f02ca4a2SJed Brown   @brief View a CeedElemRestriction
1223f02ca4a2SJed Brown 
1224f02ca4a2SJed Brown   @param[in] rstr   CeedElemRestriction to view
1225f02ca4a2SJed Brown   @param[in] stream Stream to write; typically stdout/stderr or a file
1226f02ca4a2SJed Brown 
1227f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
1228f02ca4a2SJed Brown 
12297a982d89SJeremy L. Thompson   @ref User
1230f02ca4a2SJed Brown **/
1231f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
12327509a596Sjeremylt   char stridesstr[500];
12332b730f8bSJeremy L Thompson   if (rstr->strides) {
12342b730f8bSJeremy L Thompson     sprintf(stridesstr, "[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "]", rstr->strides[0], rstr->strides[1], rstr->strides[2]);
12352b730f8bSJeremy L Thompson   } else {
1236990fdeb6SJeremy L Thompson     sprintf(stridesstr, "%" CeedInt_FMT, rstr->comp_stride);
12372b730f8bSJeremy L Thompson   }
12387509a596Sjeremylt 
12392b730f8bSJeremy L Thompson   fprintf(stream, "%sCeedElemRestriction from (%td, %" CeedInt_FMT ") to %" CeedInt_FMT " elements with %" CeedInt_FMT " nodes each and %s %s\n",
12402b730f8bSJeremy L Thompson           rstr->blk_size > 1 ? "Blocked " : "", rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
1241d979a051Sjeremylt           rstr->strides ? "strides" : "component stride", stridesstr);
1242e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1243f02ca4a2SJed Brown }
1244f02ca4a2SJed Brown 
1245f02ca4a2SJed Brown /**
1246b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
1247b11c1e72Sjeremylt 
1248ea61e9acSJeremy L Thompson   @param[in,out] rstr CeedElemRestriction to destroy
1249b11c1e72Sjeremylt 
1250b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1251dfdf5a53Sjeremylt 
12527a982d89SJeremy L. Thompson   @ref User
1253b11c1e72Sjeremylt **/
12544ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
1255393ac2cdSJeremy L Thompson   if (!*rstr || *rstr == CEED_ELEMRESTRICTION_NONE || --(*rstr)->ref_count > 0) {
1256ad6481ceSJeremy L Thompson     *rstr = NULL;
1257ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
1258ad6481ceSJeremy L Thompson   }
12596574a04fSJeremy L Thompson   CeedCheck((*rstr)->num_readers == 0, (*rstr)->ceed, CEED_ERROR_ACCESS,
12606574a04fSJeremy L Thompson             "Cannot destroy CeedElemRestriction, a process has read access to the offset data");
1261c17ec2beSJeremy L Thompson 
1262c17ec2beSJeremy L Thompson   // Only destroy backend data once between rstr and unsigned copy
12637c1dbaffSSebastian Grimberg   if ((*rstr)->rstr_base) CeedCall(CeedElemRestrictionDestroy(&(*rstr)->rstr_base));
1264c17ec2beSJeremy L Thompson   else if ((*rstr)->Destroy) CeedCall((*rstr)->Destroy(*rstr));
1265c17ec2beSJeremy L Thompson 
12662b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*rstr)->strides));
12672b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*rstr)->ceed));
12682b730f8bSJeremy L Thompson   CeedCall(CeedFree(rstr));
1269e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1270d7b241e6Sjeremylt }
1271d7b241e6Sjeremylt 
1272d7b241e6Sjeremylt /// @}
1273