xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-elemrestriction.c (revision c63574e36000d2a21e0794289cca745d44df327e)
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 /**
147a681ae63Sjeremylt   @brief Get the strides of a strided CeedElemRestriction
1487a982d89SJeremy L. Thompson 
149ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
150a681ae63Sjeremylt   @param[out] strides Variable to store strides array
1517a982d89SJeremy L. Thompson 
1527a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1537a982d89SJeremy L. Thompson 
1547a982d89SJeremy L. Thompson   @ref Backend
1557a982d89SJeremy L. Thompson **/
1562b730f8bSJeremy L Thompson int CeedElemRestrictionGetStrides(CeedElemRestriction rstr, CeedInt (*strides)[3]) {
1576574a04fSJeremy L Thompson   CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
1582b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*strides)[i] = rstr->strides[i];
159e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1607a982d89SJeremy L. Thompson }
1617a982d89SJeremy L. Thompson 
1627a982d89SJeremy L. Thompson /**
16377d1c127SSebastian Grimberg   @brief Get the backend stride status of a CeedElemRestriction
16477d1c127SSebastian Grimberg 
16577d1c127SSebastian Grimberg   @param[in]  rstr                 CeedElemRestriction
16677d1c127SSebastian Grimberg   @param[out] has_backend_strides  Variable to store stride status
16777d1c127SSebastian Grimberg 
16877d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
16977d1c127SSebastian Grimberg 
17077d1c127SSebastian Grimberg   @ref Backend
17177d1c127SSebastian Grimberg **/
17277d1c127SSebastian Grimberg int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, bool *has_backend_strides) {
17377d1c127SSebastian Grimberg   CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
17477d1c127SSebastian Grimberg   *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
17577d1c127SSebastian Grimberg                           (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
17677d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
17777d1c127SSebastian Grimberg }
17877d1c127SSebastian Grimberg 
17977d1c127SSebastian Grimberg /**
180bd33150aSjeremylt   @brief Get read-only access to a CeedElemRestriction offsets array by memtype
181bd33150aSjeremylt 
182ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction to retrieve offsets
183fcbe8c06SSebastian Grimberg   @param[in]  mem_type Memory type on which to access the array.
184fcbe8c06SSebastian Grimberg                          If the backend uses a different memory type, this will perform a copy (possibly cached).
185d1d35e2fSjeremylt   @param[out] offsets  Array on memory type mem_type
186bd33150aSjeremylt 
187bd33150aSjeremylt   @return An error code: 0 - success, otherwise - failure
188bd33150aSjeremylt 
189bd33150aSjeremylt   @ref User
190bd33150aSjeremylt **/
1912b730f8bSJeremy L Thompson int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) {
1927c1dbaffSSebastian Grimberg   if (rstr->rstr_base) {
1937c1dbaffSSebastian Grimberg     CeedCall(CeedElemRestrictionGetOffsets(rstr->rstr_base, mem_type, offsets));
194c17ec2beSJeremy L Thompson   } else {
1956574a04fSJeremy L Thompson     CeedCheck(rstr->GetOffsets, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetOffsets");
1962b730f8bSJeremy L Thompson     CeedCall(rstr->GetOffsets(rstr, mem_type, offsets));
197d1d35e2fSjeremylt     rstr->num_readers++;
198c17ec2beSJeremy L Thompson   }
199e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
200430758c8SJeremy L Thompson }
201430758c8SJeremy L Thompson 
202430758c8SJeremy L Thompson /**
203430758c8SJeremy L Thompson   @brief Restore an offsets array obtained using CeedElemRestrictionGetOffsets()
204430758c8SJeremy L Thompson 
205ea61e9acSJeremy L Thompson   @param[in] rstr    CeedElemRestriction to restore
206ea61e9acSJeremy L Thompson   @param[in] offsets Array of offset data
207430758c8SJeremy L Thompson 
208430758c8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
209430758c8SJeremy L Thompson 
210430758c8SJeremy L Thompson   @ref User
211430758c8SJeremy L Thompson **/
2122b730f8bSJeremy L Thompson int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr, const CeedInt **offsets) {
2137c1dbaffSSebastian Grimberg   if (rstr->rstr_base) {
2147c1dbaffSSebastian Grimberg     CeedCall(CeedElemRestrictionRestoreOffsets(rstr->rstr_base, offsets));
215c17ec2beSJeremy L Thompson   } else {
216430758c8SJeremy L Thompson     *offsets = NULL;
217d1d35e2fSjeremylt     rstr->num_readers--;
218c17ec2beSJeremy L Thompson   }
219e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
220bd33150aSjeremylt }
221bd33150aSjeremylt 
222bd33150aSjeremylt /**
22377d1c127SSebastian Grimberg   @brief Get read-only access to a CeedElemRestriction orientations array by memtype
2243ac43b2cSJeremy L Thompson 
22577d1c127SSebastian Grimberg   @param[in]  rstr     CeedElemRestriction to retrieve orientations
226fcbe8c06SSebastian Grimberg   @param[in]  mem_type Memory type on which to access the array.
227fcbe8c06SSebastian Grimberg                          If the backend uses a different memory type, this will perform a copy (possibly cached).
22877d1c127SSebastian Grimberg   @param[out] orients  Array on memory type mem_type
2293ac43b2cSJeremy L Thompson 
2303ac43b2cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2313ac43b2cSJeremy L Thompson 
23277d1c127SSebastian Grimberg   @ref User
2333ac43b2cSJeremy L Thompson **/
23477d1c127SSebastian Grimberg int CeedElemRestrictionGetOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const bool **orients) {
235fcbe8c06SSebastian Grimberg   CeedCheck(rstr->GetOrientations, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetOrientations");
23677d1c127SSebastian Grimberg   CeedCall(rstr->GetOrientations(rstr, mem_type, orients));
23777d1c127SSebastian Grimberg   rstr->num_readers++;
238e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2393ac43b2cSJeremy L Thompson }
2403ac43b2cSJeremy L Thompson 
2413ac43b2cSJeremy L Thompson /**
24277d1c127SSebastian Grimberg   @brief Restore an orientations array obtained using CeedElemRestrictionGetOrientations()
243b435c5a6Srezgarshakeri 
24477d1c127SSebastian Grimberg   @param[in] rstr    CeedElemRestriction to restore
24577d1c127SSebastian Grimberg   @param[in] orients Array of orientation data
246b435c5a6Srezgarshakeri 
247b435c5a6Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
248b435c5a6Srezgarshakeri 
24977d1c127SSebastian Grimberg   @ref User
250b435c5a6Srezgarshakeri **/
25177d1c127SSebastian Grimberg int CeedElemRestrictionRestoreOrientations(CeedElemRestriction rstr, const bool **orients) {
25277d1c127SSebastian Grimberg   *orients = NULL;
25377d1c127SSebastian Grimberg   rstr->num_readers--;
254b435c5a6Srezgarshakeri   return CEED_ERROR_SUCCESS;
255b435c5a6Srezgarshakeri }
256b435c5a6Srezgarshakeri 
257b435c5a6Srezgarshakeri /**
25877d1c127SSebastian Grimberg   @brief Get read-only access to a CeedElemRestriction curl-conforming orientations array by memtype
2597a982d89SJeremy L. Thompson 
26077d1c127SSebastian Grimberg   @param[in]  rstr         CeedElemRestriction to retrieve curl-conforming 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] curl_orients Array on memory type mem_type
2647a982d89SJeremy L. Thompson 
2657a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2667a982d89SJeremy L. Thompson 
26777d1c127SSebastian Grimberg   @ref User
2687a982d89SJeremy L. Thompson **/
2690c73c039SSebastian Grimberg int CeedElemRestrictionGetCurlOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt8 **curl_orients) {
270fcbe8c06SSebastian Grimberg   CeedCheck(rstr->GetCurlOrientations, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetCurlOrientations");
27177d1c127SSebastian Grimberg   CeedCall(rstr->GetCurlOrientations(rstr, mem_type, curl_orients));
27277d1c127SSebastian Grimberg   rstr->num_readers++;
27377d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
27477d1c127SSebastian Grimberg }
27577d1c127SSebastian Grimberg 
27677d1c127SSebastian Grimberg /**
27777d1c127SSebastian Grimberg   @brief Restore an orientations array obtained using CeedElemRestrictionGetCurlOrientations()
27877d1c127SSebastian Grimberg 
27977d1c127SSebastian Grimberg   @param[in] rstr         CeedElemRestriction to restore
28077d1c127SSebastian Grimberg   @param[in] curl_orients Array of orientation data
28177d1c127SSebastian Grimberg 
28277d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
28377d1c127SSebastian Grimberg 
28477d1c127SSebastian Grimberg   @ref User
28577d1c127SSebastian Grimberg **/
2860c73c039SSebastian Grimberg int CeedElemRestrictionRestoreCurlOrientations(CeedElemRestriction rstr, const CeedInt8 **curl_orients) {
28777d1c127SSebastian Grimberg   *curl_orients = NULL;
28877d1c127SSebastian Grimberg   rstr->num_readers--;
289e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2907a982d89SJeremy L. Thompson }
2917a982d89SJeremy L. Thompson 
2927a982d89SJeremy L. Thompson /**
29349fd234cSJeremy L Thompson 
29449fd234cSJeremy L Thompson   @brief Get the E-vector layout of a CeedElemRestriction
29549fd234cSJeremy L Thompson 
296ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
297fcbe8c06SSebastian Grimberg   @param[out] layout  Variable to store layout array, stored as [nodes, components, elements].
298fcbe8c06SSebastian 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]
29949fd234cSJeremy L Thompson 
30049fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
30149fd234cSJeremy L Thompson 
30249fd234cSJeremy L Thompson   @ref Backend
30349fd234cSJeremy L Thompson **/
3042b730f8bSJeremy L Thompson int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, CeedInt (*layout)[3]) {
3056574a04fSJeremy L Thompson   CeedCheck(rstr->layout[0], rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no layout data");
3062b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*layout)[i] = rstr->layout[i];
307e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
30849fd234cSJeremy L Thompson }
30949fd234cSJeremy L Thompson 
31049fd234cSJeremy L Thompson /**
31149fd234cSJeremy L Thompson 
31249fd234cSJeremy L Thompson   @brief Set the E-vector layout of a CeedElemRestriction
31349fd234cSJeremy L Thompson 
314ea61e9acSJeremy L Thompson   @param[in] rstr   CeedElemRestriction
315ea61e9acSJeremy L Thompson   @param[in] layout Variable to containing layout array, stored as [nodes, components, elements].
316ea61e9acSJeremy 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]
31749fd234cSJeremy L Thompson 
31849fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
31949fd234cSJeremy L Thompson 
32049fd234cSJeremy L Thompson   @ref Backend
32149fd234cSJeremy L Thompson **/
3222b730f8bSJeremy L Thompson int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
3232b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) rstr->layout[i] = layout[i];
324e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
32549fd234cSJeremy L Thompson }
32649fd234cSJeremy L Thompson 
32749fd234cSJeremy L Thompson /**
3287a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedElemRestriction
3297a982d89SJeremy L. Thompson 
330ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
3317a982d89SJeremy L. Thompson   @param[out] data Variable to store data
3327a982d89SJeremy L. Thompson 
3337a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3347a982d89SJeremy L. Thompson 
3357a982d89SJeremy L. Thompson   @ref Backend
3367a982d89SJeremy L. Thompson **/
337777ff853SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) {
338777ff853SJeremy L Thompson   *(void **)data = rstr->data;
339e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3407a982d89SJeremy L. Thompson }
3417a982d89SJeremy L. Thompson 
3427a982d89SJeremy L. Thompson /**
3437a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedElemRestriction
3447a982d89SJeremy L. Thompson 
345ea61e9acSJeremy L Thompson   @param[in,out] rstr CeedElemRestriction
346ea61e9acSJeremy L Thompson   @param[in]     data Data to set
3477a982d89SJeremy L. Thompson 
3487a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3497a982d89SJeremy L. Thompson 
3507a982d89SJeremy L. Thompson   @ref Backend
3517a982d89SJeremy L. Thompson **/
352777ff853SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) {
353777ff853SJeremy L Thompson   rstr->data = data;
354e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3557a982d89SJeremy L. Thompson }
3567a982d89SJeremy L. Thompson 
35734359f16Sjeremylt /**
35834359f16Sjeremylt   @brief Increment the reference counter for a CeedElemRestriction
35934359f16Sjeremylt 
360ea61e9acSJeremy L Thompson   @param[in,out] rstr ElemRestriction to increment the reference counter
36134359f16Sjeremylt 
36234359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
36334359f16Sjeremylt 
36434359f16Sjeremylt   @ref Backend
36534359f16Sjeremylt **/
3669560d06aSjeremylt int CeedElemRestrictionReference(CeedElemRestriction rstr) {
36734359f16Sjeremylt   rstr->ref_count++;
36834359f16Sjeremylt   return CEED_ERROR_SUCCESS;
36934359f16Sjeremylt }
37034359f16Sjeremylt 
3716e15d496SJeremy L Thompson /**
3726e15d496SJeremy L Thompson   @brief Estimate number of FLOPs required to apply CeedElemRestriction in t_mode
3736e15d496SJeremy L Thompson 
374ea61e9acSJeremy L Thompson   @param[in]  rstr   ElemRestriction to estimate FLOPs for
375ea61e9acSJeremy L Thompson   @param[in]  t_mode Apply restriction or transpose
376ea61e9acSJeremy L Thompson   @param[out] flops  Address of variable to hold FLOPs estimate
3776e15d496SJeremy L Thompson 
3786e15d496SJeremy L Thompson   @ref Backend
3796e15d496SJeremy L Thompson **/
3802b730f8bSJeremy L Thompson int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedSize *flops) {
381e7f679fcSJeremy L Thompson   CeedInt             e_size = rstr->num_block * rstr->block_size * rstr->elem_size * rstr->num_comp, scale = 0;
38289edb9e3SSebastian Grimberg   CeedRestrictionType rstr_type;
3831c66c397SJeremy L Thompson 
38489edb9e3SSebastian Grimberg   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
3853ac8f562SJeremy L Thompson   if (rstr_type == CEED_RESTRICTION_POINTS) e_size = rstr->num_points * rstr->num_comp;
38677d1c127SSebastian Grimberg   if (t_mode == CEED_TRANSPOSE) {
38789edb9e3SSebastian Grimberg     switch (rstr_type) {
3883ac8f562SJeremy L Thompson       case CEED_RESTRICTION_POINTS:
3893ac8f562SJeremy L Thompson         scale = 0;
3903ac8f562SJeremy L Thompson         break;
39189edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STRIDED:
39289edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STANDARD:
39377d1c127SSebastian Grimberg         scale = 1;
39489edb9e3SSebastian Grimberg         break;
39589edb9e3SSebastian Grimberg       case CEED_RESTRICTION_ORIENTED:
39677d1c127SSebastian Grimberg         scale = 2;
39789edb9e3SSebastian Grimberg         break;
39889edb9e3SSebastian Grimberg       case CEED_RESTRICTION_CURL_ORIENTED:
39977d1c127SSebastian Grimberg         scale = 6;
40089edb9e3SSebastian Grimberg         break;
4016e15d496SJeremy L Thompson     }
40277d1c127SSebastian Grimberg   } else {
40389edb9e3SSebastian Grimberg     switch (rstr_type) {
40489edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STRIDED:
40589edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STANDARD:
4063ac8f562SJeremy L Thompson       case CEED_RESTRICTION_POINTS:
40777d1c127SSebastian Grimberg         scale = 0;
40889edb9e3SSebastian Grimberg         break;
40989edb9e3SSebastian Grimberg       case CEED_RESTRICTION_ORIENTED:
41077d1c127SSebastian Grimberg         scale = 1;
41189edb9e3SSebastian Grimberg         break;
41289edb9e3SSebastian Grimberg       case CEED_RESTRICTION_CURL_ORIENTED:
41377d1c127SSebastian Grimberg         scale = 5;
41489edb9e3SSebastian Grimberg         break;
41577d1c127SSebastian Grimberg     }
41677d1c127SSebastian Grimberg   }
4176e15d496SJeremy L Thompson   *flops = e_size * scale;
4186e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4196e15d496SJeremy L Thompson }
4206e15d496SJeremy L Thompson 
4217a982d89SJeremy L. Thompson /// @}
4227a982d89SJeremy L. Thompson 
42315910d16Sjeremylt /// @cond DOXYGEN_SKIP
42415910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
42515910d16Sjeremylt /// @endcond
42615910d16Sjeremylt 
4277a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
4287a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
4297a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
4307a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
431d7b241e6Sjeremylt /// @{
432d7b241e6Sjeremylt 
4337a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
43445f1e315Sjeremylt const CeedInt CEED_STRIDES_BACKEND[3] = {0};
4357a982d89SJeremy L. Thompson 
436356036faSJeremy L Thompson /// Argument for CeedOperatorSetField indicating that the field does not requre a CeedElemRestriction
4372b730f8bSJeremy L Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = &ceed_elemrestriction_none;
4387a982d89SJeremy L. Thompson 
439d7b241e6Sjeremylt /**
440b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
441d7b241e6Sjeremylt 
442ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
443ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array
444ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
445ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
446fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
447fcbe8c06SSebastian 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.
448fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
449fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
450ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
451ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
452fcbe8c06SSebastian Grimberg   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
453fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
454fcbe8c06SSebastian Grimberg 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
455ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
456d7b241e6Sjeremylt 
457b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
458dfdf5a53Sjeremylt 
4597a982d89SJeremy L. Thompson   @ref User
460b11c1e72Sjeremylt **/
4612b730f8bSJeremy L Thompson int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
4622b730f8bSJeremy L Thompson                               CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
4635fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
4645fe0d4faSjeremylt     Ceed delegate;
4656574a04fSJeremy L Thompson 
4662b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
46777d1c127SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
4682b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
469e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
4705fe0d4faSjeremylt   }
4715fe0d4faSjeremylt 
472e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
4736574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
4746574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
4756574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
476e022e1f8SJeremy L Thompson 
4772b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
478db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
479d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
480d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
481d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
482d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
483d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
484d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
48505fa913cSJeremy L Thompson   (*rstr)->e_size      = num_elem * elem_size * num_comp;
486e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
487e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
48861a27d74SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_STANDARD;
489fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, NULL, *rstr));
490e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
491d7b241e6Sjeremylt }
492d7b241e6Sjeremylt 
493d7b241e6Sjeremylt /**
49477d1c127SSebastian Grimberg   @brief Create a CeedElemRestriction with orientation signs
495fc0567d9Srezgarshakeri 
496ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
497ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array
498ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
499ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
500fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
501fcbe8c06SSebastian 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.
502fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
503fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
504ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
505ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
506fcbe8c06SSebastian Grimberg   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
507fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
508fcbe8c06SSebastian Grimberg 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
50977d1c127SSebastian 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.
510ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
511fc0567d9Srezgarshakeri 
512fc0567d9Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
513fc0567d9Srezgarshakeri 
514fc0567d9Srezgarshakeri   @ref User
515fc0567d9Srezgarshakeri **/
5162b730f8bSJeremy L Thompson int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
51777d1c127SSebastian Grimberg                                       CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orients,
518fc0567d9Srezgarshakeri                                       CeedElemRestriction *rstr) {
519fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreate) {
520fc0567d9Srezgarshakeri     Ceed delegate;
5216574a04fSJeremy L Thompson 
5222b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
523fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
5242b730f8bSJeremy L Thompson     CeedCall(
52577d1c127SSebastian Grimberg         CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, orients, rstr));
526fc0567d9Srezgarshakeri     return CEED_ERROR_SUCCESS;
527fc0567d9Srezgarshakeri   }
528fc0567d9Srezgarshakeri 
529e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
5306574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
5316574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
5326574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
533e022e1f8SJeremy L Thompson 
5342b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
535db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
536fc0567d9Srezgarshakeri   (*rstr)->ref_count   = 1;
537fc0567d9Srezgarshakeri   (*rstr)->num_elem    = num_elem;
538fc0567d9Srezgarshakeri   (*rstr)->elem_size   = elem_size;
539fc0567d9Srezgarshakeri   (*rstr)->num_comp    = num_comp;
540fc0567d9Srezgarshakeri   (*rstr)->comp_stride = comp_stride;
541fc0567d9Srezgarshakeri   (*rstr)->l_size      = l_size;
54205fa913cSJeremy L Thompson   (*rstr)->e_size      = num_elem * elem_size * num_comp;
543e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
544e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
545fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_ORIENTED;
546fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, orients, NULL, *rstr));
54777d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
54877d1c127SSebastian Grimberg }
54977d1c127SSebastian Grimberg 
55077d1c127SSebastian Grimberg /**
55177d1c127SSebastian Grimberg   @brief Create a CeedElemRestriction with a general tridiagonal transformation matrix for curl-conforming elements
55277d1c127SSebastian Grimberg 
55377d1c127SSebastian Grimberg   @param[in]  ceed         Ceed object where the CeedElemRestriction will be created
55477d1c127SSebastian Grimberg   @param[in]  num_elem     Number of elements described in the @a offsets array
55577d1c127SSebastian Grimberg   @param[in]  elem_size    Size (number of "nodes") per element
55677d1c127SSebastian Grimberg   @param[in]  num_comp     Number of field components per interpolation node (1 for scalar fields)
557fcbe8c06SSebastian Grimberg   @param[in]  comp_stride  Stride between components for the same L-vector "node".
558fcbe8c06SSebastian 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.
559fcbe8c06SSebastian Grimberg   @param[in]  l_size       The size of the L-vector.
560fcbe8c06SSebastian Grimberg                              This vector may be larger than the elements and fields given by this restriction.
56177d1c127SSebastian Grimberg   @param[in]  mem_type     Memory type of the @a offsets array, see CeedMemType
56277d1c127SSebastian Grimberg   @param[in]  copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
563fcbe8c06SSebastian Grimberg   @param[in]  offsets      Array of shape [@a num_elem, @a elem_size].
564fcbe8c06SSebastian Grimberg                              Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i,
565fcbe8c06SSebastian Grimberg where 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
5667c1dbaffSSebastian 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]
5677c1dbaffSSebastian 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
5687c1dbaffSSebastian 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,
5697c1dbaffSSebastian Grimberg which is a way to resolve face orientation issues for 3D meshes (https://dl.acm.org/doi/pdf/10.1145/3524456).
57077d1c127SSebastian Grimberg   @param[out] rstr         Address of the variable where the newly created CeedElemRestriction will be stored
57177d1c127SSebastian Grimberg 
57277d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
57377d1c127SSebastian Grimberg 
57477d1c127SSebastian Grimberg   @ref User
57577d1c127SSebastian Grimberg **/
57677d1c127SSebastian Grimberg int CeedElemRestrictionCreateCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
5770c73c039SSebastian Grimberg                                           CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const CeedInt8 *curl_orients,
57877d1c127SSebastian Grimberg                                           CeedElemRestriction *rstr) {
579fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreate) {
58077d1c127SSebastian Grimberg     Ceed delegate;
58177d1c127SSebastian Grimberg 
58277d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
583fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
58477d1c127SSebastian Grimberg     CeedCall(CeedElemRestrictionCreateCurlOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
58577d1c127SSebastian Grimberg                                                    curl_orients, rstr));
58677d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
58777d1c127SSebastian Grimberg   }
58877d1c127SSebastian Grimberg 
589e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
59077d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
59177d1c127SSebastian Grimberg   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
59277d1c127SSebastian Grimberg   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
59377d1c127SSebastian Grimberg 
59477d1c127SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
595fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
59677d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
59777d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
59877d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
59977d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
60077d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
60177d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
60205fa913cSJeremy L Thompson   (*rstr)->e_size      = num_elem * elem_size * num_comp;
603e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
604e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
605fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_CURL_ORIENTED;
606fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, curl_orients, *rstr));
607fc0567d9Srezgarshakeri   return CEED_ERROR_SUCCESS;
608fc0567d9Srezgarshakeri }
609fc0567d9Srezgarshakeri 
610fc0567d9Srezgarshakeri /**
6117509a596Sjeremylt   @brief Create a strided CeedElemRestriction
612d7b241e6Sjeremylt 
613ea61e9acSJeremy L Thompson   @param[in]  ceed      Ceed object where the CeedElemRestriction will be created
614ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
615ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
616ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation "node" (1 for scalar fields)
617fcbe8c06SSebastian Grimberg   @param[in]  l_size    The size of the L-vector.
618fcbe8c06SSebastian Grimberg                           This vector may be larger than the elements and fields given by this restriction.
619fcbe8c06SSebastian Grimberg   @param[in]  strides   Array for strides between [nodes, components, elements].
620fcbe8c06SSebastian 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].
621fcbe8c06SSebastian Grimberg                           @a CEED_STRIDES_BACKEND may be used with vectors created by a Ceed backend.
622ea61e9acSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created CeedElemRestriction will be stored
623d7b241e6Sjeremylt 
624b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
625dfdf5a53Sjeremylt 
6267a982d89SJeremy L. Thompson   @ref User
627b11c1e72Sjeremylt **/
6282b730f8bSJeremy L Thompson int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedSize l_size, const CeedInt strides[3],
629f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
6305fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
6315fe0d4faSjeremylt     Ceed delegate;
632b04eb3d9SSebastian Grimberg 
6332b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
634fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
6352b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, l_size, strides, rstr));
636e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6375fe0d4faSjeremylt   }
6385fe0d4faSjeremylt 
639e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
6406574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
6416574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
642e7f679fcSJeremy 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");
643e022e1f8SJeremy L Thompson 
6442b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
645db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
646d1d35e2fSjeremylt   (*rstr)->ref_count  = 1;
647d1d35e2fSjeremylt   (*rstr)->num_elem   = num_elem;
648d1d35e2fSjeremylt   (*rstr)->elem_size  = elem_size;
649d1d35e2fSjeremylt   (*rstr)->num_comp   = num_comp;
650d1d35e2fSjeremylt   (*rstr)->l_size     = l_size;
65105fa913cSJeremy L Thompson   (*rstr)->e_size     = num_elem * elem_size * num_comp;
652e7f679fcSJeremy L Thompson   (*rstr)->num_block  = num_elem;
653e7f679fcSJeremy L Thompson   (*rstr)->block_size = 1;
654fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type  = CEED_RESTRICTION_STRIDED;
6552b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
6562b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
657fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
658e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
659d7b241e6Sjeremylt }
660d7b241e6Sjeremylt 
661d7b241e6Sjeremylt /**
6623ac8f562SJeremy L Thompson   @brief Create a points CeedElemRestriction, for restricting for restricting from a all local points to the current element in which they are
6633ac8f562SJeremy L Thompson  located.
6643ac8f562SJeremy L Thompson 
6653ac8f562SJeremy L Thompson   The offsets array is arranged as
6663ac8f562SJeremy L Thompson 
6673ac8f562SJeremy L Thompson   element_0_start_index
6683ac8f562SJeremy L Thompson   element_1_start_index
6693ac8f562SJeremy L Thompson   ...
6703ac8f562SJeremy L Thompson   element_n_start_index
6713ac8f562SJeremy L Thompson   element_n_stop_index
6723ac8f562SJeremy L Thompson   element_0_point_0
6733ac8f562SJeremy L Thompson   element_0_point_1
6743ac8f562SJeremy L Thompson   ...
6753ac8f562SJeremy L Thompson 
6763ac8f562SJeremy L Thompson   @param[in]  ceed          Ceed object where the CeedElemRestriction will be created
6773ac8f562SJeremy L Thompson   @param[in]  num_elem      Number of elements described in the @a offsets array
6783ac8f562SJeremy L Thompson   @param[in]  num_points    Number of points described in the @a offsets array
6793ac8f562SJeremy L Thompson   @param[in]  num_comp      Number of field components per interpolation node (1 for scalar fields).
6803ac8f562SJeremy L Thompson                               Components are assumed to be contiguous by point.
6813ac8f562SJeremy L Thompson   @param[in]  l_size        The size of the L-vector.
6823ac8f562SJeremy L Thompson                               This vector may be larger than the elements and fields given by this restriction.
6833ac8f562SJeremy L Thompson   @param[in]  mem_type      Memory type of the @a offsets array, see CeedMemType
6843ac8f562SJeremy L Thompson   @param[in]  copy_mode     Copy mode for the @a offsets array, see CeedCopyMode
6853ac8f562SJeremy L Thompson   @param[in]  offsets       Array of size num_elem + 1 + num_points.
6863ac8f562SJeremy L Thompson                               The first portion of the offsets array holds the ranges of indices corresponding to each element.
6873ac8f562SJeremy L Thompson                               The second portion holds the indices for each element.
6883ac8f562SJeremy L Thompson   @param[out] rstr          Address of the variable where the newly created CeedElemRestriction will be stored
6893ac8f562SJeremy L Thompson 
6903ac8f562SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
6913ac8f562SJeremy L Thompson 
6923ac8f562SJeremy L Thompson   @ref Backend
6933ac8f562SJeremy L Thompson  **/
6943ac8f562SJeremy L Thompson int CeedElemRestrictionCreateAtPoints(Ceed ceed, CeedInt num_elem, CeedInt num_points, CeedInt num_comp, CeedSize l_size, CeedMemType mem_type,
6953ac8f562SJeremy L Thompson                                       CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
6963ac8f562SJeremy L Thompson   if (!ceed->ElemRestrictionCreateAtPoints) {
6973ac8f562SJeremy L Thompson     Ceed delegate;
6983ac8f562SJeremy L Thompson 
6993ac8f562SJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
7003ac8f562SJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateAtPoints");
7013ac8f562SJeremy L Thompson     CeedCall(CeedElemRestrictionCreateAtPoints(delegate, num_elem, num_points, num_comp, l_size, mem_type, copy_mode, offsets, rstr));
7023ac8f562SJeremy L Thompson     return CEED_ERROR_SUCCESS;
7033ac8f562SJeremy L Thompson   }
7043ac8f562SJeremy L Thompson 
7053ac8f562SJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
7063ac8f562SJeremy L Thompson   CeedCheck(num_points >= 0, ceed, CEED_ERROR_DIMENSION, "Number of points must be non-negative");
7073ac8f562SJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
7083ac8f562SJeremy L Thompson   CeedCheck(l_size >= num_points * num_comp, ceed, CEED_ERROR_DIMENSION, "L-vector must be at least num_points * num_comp");
7093ac8f562SJeremy L Thompson 
7103ac8f562SJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
7113ac8f562SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
7123ac8f562SJeremy L Thompson   (*rstr)->ref_count  = 1;
7133ac8f562SJeremy L Thompson   (*rstr)->num_elem   = num_elem;
7143ac8f562SJeremy L Thompson   (*rstr)->num_points = num_points;
7153ac8f562SJeremy L Thompson   (*rstr)->num_comp   = num_comp;
7163ac8f562SJeremy L Thompson   (*rstr)->l_size     = l_size;
71705fa913cSJeremy L Thompson   (*rstr)->e_size     = num_points * num_comp;
71805fa913cSJeremy L Thompson   (*rstr)->num_block  = num_elem;
7193ac8f562SJeremy L Thompson   (*rstr)->block_size = 1;
7203ac8f562SJeremy L Thompson   (*rstr)->rstr_type  = CEED_RESTRICTION_POINTS;
7213ac8f562SJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateAtPoints(mem_type, copy_mode, offsets, NULL, NULL, *rstr));
7223ac8f562SJeremy L Thompson   return CEED_ERROR_SUCCESS;
7233ac8f562SJeremy L Thompson }
7243ac8f562SJeremy L Thompson 
7253ac8f562SJeremy L Thompson /**
726b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
727d7b241e6Sjeremylt 
7283ac8f562SJeremy L Thompson   @param[in]  ceed          Ceed object where the CeedElemRestriction will be created
7293ac8f562SJeremy L Thompson   @param[in]  num_elem      Number of elements described in the @a offsets array
730ea61e9acSJeremy L Thompson   @param[in]  elem_size     Size (number of unknowns) per element
731e7f679fcSJeremy L Thompson   @param[in]  block_size    Number of elements in a block
732ea61e9acSJeremy L Thompson   @param[in]  num_comp      Number of field components per interpolation node (1 for scalar fields)
733fcbe8c06SSebastian Grimberg   @param[in]  comp_stride   Stride between components for the same L-vector "node".
734fcbe8c06SSebastian 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.
735fcbe8c06SSebastian Grimberg   @param[in]  l_size        The size of the L-vector.
736fcbe8c06SSebastian Grimberg                               This vector may be larger than the elements and fields given by this restriction.
737ea61e9acSJeremy L Thompson   @param[in]  mem_type      Memory type of the @a offsets array, see CeedMemType
738ea61e9acSJeremy L Thompson   @param[in]  copy_mode     Copy mode for the @a offsets array, see CeedCopyMode
739fcbe8c06SSebastian Grimberg   @param[in]  offsets       Array of shape [@a num_elem, @a elem_size].
740e7f679fcSJeremy L Thompson                               Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i,
741e7f679fcSJeremy 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
742e7f679fcSJeremy L Thompson  for the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
743ea61e9acSJeremy L Thompson   @param[out] rstr          Address of the variable where the newly created CeedElemRestriction will be stored
744d7b241e6Sjeremylt 
745b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
746dfdf5a53Sjeremylt 
7477a982d89SJeremy L. Thompson   @ref Backend
748b11c1e72Sjeremylt  **/
749e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedInt comp_stride,
7502b730f8bSJeremy L Thompson                                      CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets,
7514ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
7521c66c397SJeremy L Thompson   CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
753d7b241e6Sjeremylt 
7545fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
7555fe0d4faSjeremylt     Ceed delegate;
7566574a04fSJeremy L Thompson 
7572b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
7586402da51SJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
759e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
760e7f679fcSJeremy L Thompson                                               rstr));
761e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
7625fe0d4faSjeremylt   }
763d7b241e6Sjeremylt 
764e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
7656574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
766e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
7676574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
7686574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
769e022e1f8SJeremy L Thompson 
770e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
771e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
772d7b241e6Sjeremylt 
773db002c03SJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
774db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
775d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
776d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
777d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
778d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
779d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
780d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
78105fa913cSJeremy L Thompson   (*rstr)->e_size      = num_block * block_size * elem_size * num_comp;
782e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
783e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
78461a27d74SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_STANDARD;
785e7f679fcSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL, NULL, *rstr));
7861c66c397SJeremy L Thompson   if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
787e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
788d7b241e6Sjeremylt }
789d7b241e6Sjeremylt 
790b11c1e72Sjeremylt /**
79177d1c127SSebastian Grimberg   @brief Create a blocked oriented CeedElemRestriction, typically only called by backends
79277d1c127SSebastian Grimberg 
79377d1c127SSebastian Grimberg   @param[in]  ceed          Ceed object where the CeedElemRestriction will be created.
79477d1c127SSebastian Grimberg   @param[in]  num_elem      Number of elements described in the @a offsets array.
79577d1c127SSebastian Grimberg   @param[in]  elem_size     Size (number of unknowns) per element
796e7f679fcSJeremy L Thompson   @param[in]  block_size    Number of elements in a block
79777d1c127SSebastian Grimberg   @param[in]  num_comp      Number of field components per interpolation node (1 for scalar fields)
798fcbe8c06SSebastian Grimberg   @param[in]  comp_stride   Stride between components for the same L-vector "node".
799fcbe8c06SSebastian 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.
800fcbe8c06SSebastian Grimberg   @param[in]  l_size        The size of the L-vector.
801fcbe8c06SSebastian Grimberg                               This vector may be larger than the elements and fields given by this restriction.
80277d1c127SSebastian Grimberg   @param[in]  mem_type      Memory type of the @a offsets array, see CeedMemType
80377d1c127SSebastian Grimberg   @param[in]  copy_mode     Copy mode for the @a offsets array, see CeedCopyMode
804fcbe8c06SSebastian Grimberg   @param[in]  offsets       Array of shape [@a num_elem, @a elem_size].
805fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
806fcbe8c06SSebastian 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
807fcbe8c06SSebastian Grimberg  the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
808fcbe8c06SSebastian 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.
809fcbe8c06SSebastian Grimberg                               Will also be permuted and padded similarly to @a offsets.
81077d1c127SSebastian Grimberg   @param[out] rstr          Address of the variable where the newly created CeedElemRestriction will be stored
81177d1c127SSebastian Grimberg 
81277d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
81377d1c127SSebastian Grimberg 
81477d1c127SSebastian Grimberg   @ref Backend
81577d1c127SSebastian Grimberg  **/
816e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp,
817e7f679fcSJeremy L Thompson                                              CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode,
818e7f679fcSJeremy L Thompson                                              const CeedInt *offsets, const bool *orients, CeedElemRestriction *rstr) {
819e7f679fcSJeremy L Thompson   bool    *block_orients;
8201c66c397SJeremy L Thompson   CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
82177d1c127SSebastian Grimberg 
822fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreateBlocked) {
82377d1c127SSebastian Grimberg     Ceed delegate;
82477d1c127SSebastian Grimberg 
82577d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
826fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
827e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode,
82877d1c127SSebastian Grimberg                                                       offsets, orients, rstr));
82977d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
83077d1c127SSebastian Grimberg   }
83177d1c127SSebastian Grimberg 
83277d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
833e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
83477d1c127SSebastian Grimberg   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
83577d1c127SSebastian Grimberg   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
83677d1c127SSebastian Grimberg 
837e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
838e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_orients));
839e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
840e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOrients(orients, block_orients, num_block, num_elem, block_size, elem_size));
84177d1c127SSebastian Grimberg 
842fcbe8c06SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
843fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
84477d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
84577d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
84677d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
84777d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
84877d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
84977d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
85005fa913cSJeremy L Thompson   (*rstr)->e_size      = num_block * block_size * elem_size * num_comp;
851e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
852e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
853fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_ORIENTED;
854e7f679fcSJeremy L Thompson   CeedCall(
855e7f679fcSJeremy L Thompson       ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, (const bool *)block_orients, NULL, *rstr));
8561c66c397SJeremy L Thompson   if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
85777d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
85877d1c127SSebastian Grimberg }
85977d1c127SSebastian Grimberg 
86077d1c127SSebastian Grimberg /**
86177d1c127SSebastian Grimberg   @brief Create a blocked curl-oriented CeedElemRestriction, typically only called by backends
86277d1c127SSebastian Grimberg 
86377d1c127SSebastian Grimberg   @param[in]  ceed           Ceed object where the CeedElemRestriction will be created.
86477d1c127SSebastian Grimberg   @param[in]  num_elem       Number of elements described in the @a offsets array.
86577d1c127SSebastian Grimberg   @param[in]  elem_size      Size (number of unknowns) per element
866e7f679fcSJeremy L Thompson   @param[in]  block_size     Number of elements in a block
86777d1c127SSebastian Grimberg   @param[in]  num_comp       Number of field components per interpolation node (1 for scalar fields)
868fcbe8c06SSebastian Grimberg   @param[in]  comp_stride    Stride between components for the same L-vector "node".
869fcbe8c06SSebastian 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.
870fcbe8c06SSebastian Grimberg   @param[in]  l_size         The size of the L-vector.
871fcbe8c06SSebastian Grimberg                                This vector may be larger than the elements and fields given by this restriction.
87277d1c127SSebastian Grimberg   @param[in]  mem_type       Memory type of the @a offsets array, see CeedMemType
87377d1c127SSebastian Grimberg   @param[in]  copy_mode      Copy mode for the @a offsets array, see CeedCopyMode
874fcbe8c06SSebastian Grimberg   @param[in]  offsets        Array of shape [@a num_elem, @a elem_size].
875fcbe8c06SSebastian Grimberg                              Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i,
876fcbe8c06SSebastian 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
877fcbe8c06SSebastian Grimberg for the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
8787c1dbaffSSebastian 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]
8797c1dbaffSSebastian 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
8807c1dbaffSSebastian 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,
8817c1dbaffSSebastian 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
8827c1dbaffSSebastian Grimberg similarly to @a offsets.
88377d1c127SSebastian Grimberg   @param[out] rstr           Address of the variable where the newly created CeedElemRestriction will be stored
88477d1c127SSebastian Grimberg 
88577d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
88677d1c127SSebastian Grimberg 
88777d1c127SSebastian Grimberg   @ref Backend
88877d1c127SSebastian Grimberg  **/
889e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp,
89077d1c127SSebastian Grimberg                                                  CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode,
8910c73c039SSebastian Grimberg                                                  const CeedInt *offsets, const CeedInt8 *curl_orients, CeedElemRestriction *rstr) {
892e7f679fcSJeremy L Thompson   CeedInt8 *block_curl_orients;
8931c66c397SJeremy L Thompson   CeedInt  *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size);
89477d1c127SSebastian Grimberg 
895fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreateBlocked) {
89677d1c127SSebastian Grimberg     Ceed delegate;
89777d1c127SSebastian Grimberg 
89877d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
899fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
900e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedCurlOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type,
901e7f679fcSJeremy L Thompson                                                           copy_mode, offsets, curl_orients, rstr));
90277d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
90377d1c127SSebastian Grimberg   }
90477d1c127SSebastian Grimberg 
905e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
90677d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
907e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
90877d1c127SSebastian Grimberg   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
90977d1c127SSebastian Grimberg   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
91077d1c127SSebastian Grimberg 
911e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
912e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * 3 * elem_size, &block_curl_orients));
913e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
914e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadCurlOrients(curl_orients, block_curl_orients, num_block, num_elem, block_size, 3 * elem_size));
91577d1c127SSebastian Grimberg 
916fcbe8c06SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
917fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
91877d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
91977d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
92077d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
92177d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
92277d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
92377d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
92405fa913cSJeremy L Thompson   (*rstr)->e_size      = num_block * block_size * elem_size * num_comp;
925e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
926e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
927fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_CURL_ORIENTED;
928e7f679fcSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL,
929e7f679fcSJeremy L Thompson                                               (const CeedInt8 *)block_curl_orients, *rstr));
9301c66c397SJeremy L Thompson   if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets));
93177d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
93277d1c127SSebastian Grimberg }
93377d1c127SSebastian Grimberg 
93477d1c127SSebastian Grimberg /**
93577d1c127SSebastian Grimberg   @brief Create a blocked strided CeedElemRestriction, typically only called by backends
9367509a596Sjeremylt 
937ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
938ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described by the restriction
939ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
940e7f679fcSJeremy L Thompson   @param[in]  block_size  Number of elements in a block
941ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
942fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
943fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
944fcbe8c06SSebastian Grimberg   @param[in]  strides     Array for strides between [nodes, components, elements].
945fcbe8c06SSebastian 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].
946fcbe8c06SSebastian Grimberg                             @a CEED_STRIDES_BACKEND may be used with vectors created by a Ceed backend.
947ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
9487509a596Sjeremylt 
9497509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
9507509a596Sjeremylt 
9517a982d89SJeremy L. Thompson   @ref User
9527509a596Sjeremylt **/
953e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedSize l_size,
9548621c6c6SJeremy L Thompson                                             const CeedInt strides[3], CeedElemRestriction *rstr) {
955e7f679fcSJeremy L Thompson   CeedInt num_block = (num_elem / block_size) + !!(num_elem % block_size);
9567509a596Sjeremylt 
9577509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
9587509a596Sjeremylt     Ceed delegate;
9596574a04fSJeremy L Thompson 
9602b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
961fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
962e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, block_size, num_comp, l_size, strides, rstr));
963e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
9647509a596Sjeremylt   }
9657509a596Sjeremylt 
966e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
9676574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
968e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
9696574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
970e7f679fcSJeremy 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");
971e022e1f8SJeremy L Thompson 
9722b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
973db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
974d1d35e2fSjeremylt   (*rstr)->ref_count  = 1;
975d1d35e2fSjeremylt   (*rstr)->num_elem   = num_elem;
976d1d35e2fSjeremylt   (*rstr)->elem_size  = elem_size;
977d1d35e2fSjeremylt   (*rstr)->num_comp   = num_comp;
978d1d35e2fSjeremylt   (*rstr)->l_size     = l_size;
97905fa913cSJeremy L Thompson   (*rstr)->e_size     = num_block * block_size * elem_size * num_comp;
980e7f679fcSJeremy L Thompson   (*rstr)->num_block  = num_block;
981e7f679fcSJeremy L Thompson   (*rstr)->block_size = block_size;
982fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type  = CEED_RESTRICTION_STRIDED;
9832b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
9842b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
985fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
986e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
9877509a596Sjeremylt }
9887509a596Sjeremylt 
9897509a596Sjeremylt /**
9907c1dbaffSSebastian Grimberg   @brief Copy the pointer to a CeedElemRestriction and set `CeedElemRestrictionApply()` implementation to use the unsigned version.
991c17ec2beSJeremy L Thompson 
992c17ec2beSJeremy L Thompson   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
993c17ec2beSJeremy L Thompson 
994c17ec2beSJeremy L Thompson   @param[in]     rstr          CeedElemRestriction to create unsigned reference to
995c17ec2beSJeremy L Thompson   @param[in,out] rstr_unsigned Variable to store unsigned CeedElemRestriction
996c17ec2beSJeremy L Thompson 
997c17ec2beSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
998c17ec2beSJeremy L Thompson 
999c17ec2beSJeremy L Thompson   @ref User
1000c17ec2beSJeremy L Thompson **/
1001c17ec2beSJeremy L Thompson int CeedElemRestrictionCreateUnsignedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unsigned) {
1002c17ec2beSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr_unsigned));
1003c17ec2beSJeremy L Thompson 
1004c17ec2beSJeremy L Thompson   // Copy old rstr
1005c17ec2beSJeremy L Thompson   memcpy(*rstr_unsigned, rstr, sizeof(struct CeedElemRestriction_private));
1006c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ceed = NULL;
1007c17ec2beSJeremy L Thompson   CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unsigned)->ceed));
1008c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ref_count = 1;
1009c17ec2beSJeremy L Thompson   (*rstr_unsigned)->strides   = NULL;
1010c17ec2beSJeremy L Thompson   if (rstr->strides) {
1011c17ec2beSJeremy L Thompson     CeedCall(CeedMalloc(3, &(*rstr_unsigned)->strides));
1012c17ec2beSJeremy L Thompson     for (CeedInt i = 0; i < 3; i++) (*rstr_unsigned)->strides[i] = rstr->strides[i];
1013c17ec2beSJeremy L Thompson   }
10147c1dbaffSSebastian Grimberg   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unsigned)->rstr_base));
1015c17ec2beSJeremy L Thompson 
1016c17ec2beSJeremy L Thompson   // Override Apply
1017c17ec2beSJeremy L Thompson   (*rstr_unsigned)->Apply = rstr->ApplyUnsigned;
1018c17ec2beSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1019c17ec2beSJeremy L Thompson }
1020c17ec2beSJeremy L Thompson 
1021c17ec2beSJeremy L Thompson /**
10227c1dbaffSSebastian Grimberg   @brief Copy the pointer to a CeedElemRestriction and set `CeedElemRestrictionApply()` implementation to use the unoriented version.
10237c1dbaffSSebastian Grimberg 
10247c1dbaffSSebastian Grimberg   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
10257c1dbaffSSebastian Grimberg 
10267c1dbaffSSebastian Grimberg   @param[in]     rstr            CeedElemRestriction to create unoriented reference to
10277c1dbaffSSebastian Grimberg   @param[in,out] rstr_unoriented Variable to store unoriented CeedElemRestriction
10287c1dbaffSSebastian Grimberg 
10297c1dbaffSSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
10307c1dbaffSSebastian Grimberg 
10317c1dbaffSSebastian Grimberg   @ref User
10327c1dbaffSSebastian Grimberg **/
10337c1dbaffSSebastian Grimberg int CeedElemRestrictionCreateUnorientedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unoriented) {
10347c1dbaffSSebastian Grimberg   CeedCall(CeedCalloc(1, rstr_unoriented));
10357c1dbaffSSebastian Grimberg 
10367c1dbaffSSebastian Grimberg   // Copy old rstr
10377c1dbaffSSebastian Grimberg   memcpy(*rstr_unoriented, rstr, sizeof(struct CeedElemRestriction_private));
10387c1dbaffSSebastian Grimberg   (*rstr_unoriented)->ceed = NULL;
10397c1dbaffSSebastian Grimberg   CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unoriented)->ceed));
10407c1dbaffSSebastian Grimberg   (*rstr_unoriented)->ref_count = 1;
10417c1dbaffSSebastian Grimberg   (*rstr_unoriented)->strides   = NULL;
10427c1dbaffSSebastian Grimberg   if (rstr->strides) {
10437c1dbaffSSebastian Grimberg     CeedCall(CeedMalloc(3, &(*rstr_unoriented)->strides));
10447c1dbaffSSebastian Grimberg     for (CeedInt i = 0; i < 3; i++) (*rstr_unoriented)->strides[i] = rstr->strides[i];
10457c1dbaffSSebastian Grimberg   }
10467c1dbaffSSebastian Grimberg   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unoriented)->rstr_base));
10477c1dbaffSSebastian Grimberg 
10487c1dbaffSSebastian Grimberg   // Override Apply
10497c1dbaffSSebastian Grimberg   (*rstr_unoriented)->Apply = rstr->ApplyUnoriented;
10507c1dbaffSSebastian Grimberg   return CEED_ERROR_SUCCESS;
10517c1dbaffSSebastian Grimberg }
10527c1dbaffSSebastian Grimberg 
10537c1dbaffSSebastian Grimberg /**
1054ea61e9acSJeremy L Thompson   @brief Copy the pointer to a CeedElemRestriction.
10559fd66db6SSebastian Grimberg 
1056ea61e9acSJeremy L Thompson   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
10579560d06aSjeremylt 
10589fd66db6SSebastian 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.
10599fd66db6SSebastian Grimberg         This CeedElemRestriction will be destroyed if `rstr_copy` is the only reference to this CeedElemRestriction.
1060ea61e9acSJeremy L Thompson 
1061ea61e9acSJeremy L Thompson   @param[in]     rstr      CeedElemRestriction to copy reference to
1062ea61e9acSJeremy L Thompson   @param[in,out] rstr_copy Variable to store copied reference
10639560d06aSjeremylt 
10649560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
10659560d06aSjeremylt 
10669560d06aSjeremylt   @ref User
10679560d06aSjeremylt **/
10682b730f8bSJeremy L Thompson int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_copy) {
1069393ac2cdSJeremy L Thompson   if (rstr != CEED_ELEMRESTRICTION_NONE) CeedCall(CeedElemRestrictionReference(rstr));
10702b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionDestroy(rstr_copy));
10719560d06aSjeremylt   *rstr_copy = rstr;
10729560d06aSjeremylt   return CEED_ERROR_SUCCESS;
10739560d06aSjeremylt }
10749560d06aSjeremylt 
10759560d06aSjeremylt /**
1076b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
1077b11c1e72Sjeremylt 
1078ea61e9acSJeremy L Thompson   @param[in]  rstr  CeedElemRestriction
1079ea61e9acSJeremy L Thompson   @param[out] l_vec The address of the L-vector to be created, or NULL
1080ea61e9acSJeremy L Thompson   @param[out] e_vec The address of the E-vector to be created, or NULL
1081b11c1e72Sjeremylt 
1082b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1083dfdf5a53Sjeremylt 
10847a982d89SJeremy L. Thompson   @ref User
1085b11c1e72Sjeremylt **/
10862b730f8bSJeremy L Thompson int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, CeedVector *e_vec) {
1087d2643443SJeremy L Thompson   CeedSize e_size, l_size;
1088d1d35e2fSjeremylt   l_size = rstr->l_size;
1089e7f679fcSJeremy L Thompson   e_size = rstr->num_block * rstr->block_size * rstr->elem_size * rstr->num_comp;
10902b730f8bSJeremy L Thompson   if (l_vec) CeedCall(CeedVectorCreate(rstr->ceed, l_size, l_vec));
10912b730f8bSJeremy L Thompson   if (e_vec) CeedCall(CeedVectorCreate(rstr->ceed, e_size, e_vec));
1092e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1093d7b241e6Sjeremylt }
1094d7b241e6Sjeremylt 
1095d7b241e6Sjeremylt /**
1096d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
1097d7b241e6Sjeremylt 
1098ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
1099ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1100ea61e9acSJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
1101fcbe8c06SSebastian Grimberg   @param[out] ru      Output vector (of shape [@a num_elem * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
1102fcbe8c06SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
1103ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
1104b11c1e72Sjeremylt 
1105b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1106dfdf5a53Sjeremylt 
11077a982d89SJeremy L. Thompson   @ref User
1108b11c1e72Sjeremylt **/
11092b730f8bSJeremy L Thompson int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
1110d7b241e6Sjeremylt   CeedInt m, n;
1111d7b241e6Sjeremylt 
1112d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
111305fa913cSJeremy L Thompson     m = rstr->e_size;
1114d1d35e2fSjeremylt     n = rstr->l_size;
1115d7b241e6Sjeremylt   } else {
1116d1d35e2fSjeremylt     m = rstr->l_size;
111705fa913cSJeremy L Thompson     n = rstr->e_size;
1118d7b241e6Sjeremylt   }
111905fa913cSJeremy L Thompson   CeedCheck(n <= u->length, rstr->ceed, CEED_ERROR_DIMENSION,
11206574a04fSJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
112105fa913cSJeremy L Thompson   CeedCheck(m <= ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
11226574a04fSJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
11232b730f8bSJeremy L Thompson   if (rstr->num_elem > 0) CeedCall(rstr->Apply(rstr, t_mode, u, ru, request));
1124e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1125d7b241e6Sjeremylt }
1126d7b241e6Sjeremylt 
1127d7b241e6Sjeremylt /**
11283ac8f562SJeremy L Thompson   @brief Restrict an L-vector of points to a single element or apply its transpose
11293ac8f562SJeremy L Thompson 
11303ac8f562SJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
11313ac8f562SJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
11323ac8f562SJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
11333ac8f562SJeremy L Thompson   @param[out] ru      Output vector (of shape [@a num_elem * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
11343ac8f562SJeremy L Thompson                         Ordering of the e-vector is decided by the backend.
11353ac8f562SJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
11363ac8f562SJeremy L Thompson 
11373ac8f562SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
11383ac8f562SJeremy L Thompson 
11393ac8f562SJeremy L Thompson   @ref User
11403ac8f562SJeremy L Thompson **/
114105fa913cSJeremy L Thompson int CeedElemRestrictionApplyAtPointsInElement(CeedElemRestriction rstr, CeedInt elem, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
11423ac8f562SJeremy L Thompson                                               CeedRequest *request) {
11433ac8f562SJeremy L Thompson   CeedInt m, n;
11443ac8f562SJeremy L Thompson 
11453ac8f562SJeremy L Thompson   if (t_mode == CEED_NOTRANSPOSE) {
11463ac8f562SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, elem, &m));
11473ac8f562SJeremy L Thompson     n = rstr->l_size;
11483ac8f562SJeremy L Thompson   } else {
11493ac8f562SJeremy L Thompson     m = rstr->l_size;
11503ac8f562SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, elem, &n));
11513ac8f562SJeremy L Thompson   }
11523ac8f562SJeremy L Thompson   CeedCheck(n <= u->length, rstr->ceed, CEED_ERROR_DIMENSION,
11533ac8f562SJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT
11543ac8f562SJeremy L Thompson             ") for element %" CeedInt_FMT,
11553ac8f562SJeremy L Thompson             u->length, m, n, elem);
11563ac8f562SJeremy L Thompson   CeedCheck(m <= ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
11573ac8f562SJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT
11583ac8f562SJeremy L Thompson             ") for element %" CeedInt_FMT,
11593ac8f562SJeremy L Thompson             ru->length, m, n, elem);
11600930e4e7SJeremy L Thompson   CeedCheck(elem < rstr->num_elem, rstr->ceed, CEED_ERROR_DIMENSION,
11613ac8f562SJeremy L Thompson             "Cannot retrieve element %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", elem, elem, rstr->num_elem);
116205fa913cSJeremy L Thompson   if (rstr->num_elem > 0) CeedCall(rstr->ApplyAtPointsInElement(rstr, elem, t_mode, u, ru, request));
11633ac8f562SJeremy L Thompson   return CEED_ERROR_SUCCESS;
11643ac8f562SJeremy L Thompson }
11653ac8f562SJeremy L Thompson 
11663ac8f562SJeremy L Thompson /**
1167d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
1168be9261b7Sjeremylt 
1169ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
1170e7f679fcSJeremy 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
1171e7f679fcSJeremy L Thompson [3*block_size : 4*block_size]
1172ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1173ea61e9acSJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
1174e7f679fcSJeremy L Thompson   @param[out] ru      Output vector (of shape [@a block_size * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
1175fcbe8c06SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
1176ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
1177be9261b7Sjeremylt 
1178be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
1179be9261b7Sjeremylt 
11807a982d89SJeremy L. Thompson   @ref Backend
1181be9261b7Sjeremylt **/
11822b730f8bSJeremy L Thompson int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
11832b730f8bSJeremy L Thompson                                   CeedRequest *request) {
1184be9261b7Sjeremylt   CeedInt m, n;
1185be9261b7Sjeremylt 
11866402da51SJeremy L Thompson   CeedCheck(rstr->ApplyBlock, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionApplyBlock");
11876402da51SJeremy L Thompson 
1188d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
1189e7f679fcSJeremy L Thompson     m = rstr->block_size * rstr->elem_size * rstr->num_comp;
1190d1d35e2fSjeremylt     n = rstr->l_size;
1191be9261b7Sjeremylt   } else {
1192d1d35e2fSjeremylt     m = rstr->l_size;
1193e7f679fcSJeremy L Thompson     n = rstr->block_size * rstr->elem_size * rstr->num_comp;
1194be9261b7Sjeremylt   }
11956574a04fSJeremy L Thompson   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
11966574a04fSJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
11976574a04fSJeremy L Thompson   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
11986574a04fSJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
1199e7f679fcSJeremy L Thompson   CeedCheck(rstr->block_size * block <= rstr->num_elem, rstr->ceed, CEED_ERROR_DIMENSION,
1200e7f679fcSJeremy L Thompson             "Cannot retrieve block %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", block, rstr->block_size * block,
12016574a04fSJeremy L Thompson             rstr->num_elem);
12022b730f8bSJeremy L Thompson   CeedCall(rstr->ApplyBlock(rstr, block, t_mode, u, ru, request));
1203e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1204be9261b7Sjeremylt }
1205be9261b7Sjeremylt 
1206be9261b7Sjeremylt /**
1207b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedElemRestriction
1208b7c9bbdaSJeremy L Thompson 
1209ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
1210b7c9bbdaSJeremy L Thompson   @param[out] ceed Variable to store Ceed
1211b7c9bbdaSJeremy L Thompson 
1212b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1213b7c9bbdaSJeremy L Thompson 
1214b7c9bbdaSJeremy L Thompson   @ref Advanced
1215b7c9bbdaSJeremy L Thompson **/
1216b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
1217b7c9bbdaSJeremy L Thompson   *ceed = rstr->ceed;
1218b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1219b7c9bbdaSJeremy L Thompson }
1220b7c9bbdaSJeremy L Thompson 
1221b7c9bbdaSJeremy L Thompson /**
1222d979a051Sjeremylt   @brief Get the L-vector component stride
1223a681ae63Sjeremylt 
1224ea61e9acSJeremy L Thompson   @param[in]  rstr        CeedElemRestriction
1225d1d35e2fSjeremylt   @param[out] comp_stride Variable to store component stride
1226a681ae63Sjeremylt 
1227a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1228a681ae63Sjeremylt 
1229b7c9bbdaSJeremy L Thompson   @ref Advanced
1230a681ae63Sjeremylt **/
12312b730f8bSJeremy L Thompson int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, CeedInt *comp_stride) {
1232d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
1233e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1234a681ae63Sjeremylt }
1235a681ae63Sjeremylt 
1236a681ae63Sjeremylt /**
1237a681ae63Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
1238a681ae63Sjeremylt 
1239ea61e9acSJeremy L Thompson   @param[in] rstr      CeedElemRestriction
1240d1d35e2fSjeremylt   @param[out] num_elem Variable to store number of elements
1241a681ae63Sjeremylt 
1242a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1243a681ae63Sjeremylt 
1244b7c9bbdaSJeremy L Thompson   @ref Advanced
1245a681ae63Sjeremylt **/
12462b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, CeedInt *num_elem) {
1247d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
1248e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1249a681ae63Sjeremylt }
1250a681ae63Sjeremylt 
1251a681ae63Sjeremylt /**
1252a681ae63Sjeremylt   @brief Get the size of elements in the CeedElemRestriction
1253a681ae63Sjeremylt 
1254ea61e9acSJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
1255d1d35e2fSjeremylt   @param[out] elem_size Variable to store size of elements
1256a681ae63Sjeremylt 
1257a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1258a681ae63Sjeremylt 
1259b7c9bbdaSJeremy L Thompson   @ref Advanced
1260a681ae63Sjeremylt **/
12612b730f8bSJeremy L Thompson int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, CeedInt *elem_size) {
1262d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
12632c7e7413SJeremy L Thompson   return CEED_ERROR_SUCCESS;
12642c7e7413SJeremy L Thompson }
12652c7e7413SJeremy L Thompson 
12662c7e7413SJeremy L Thompson /**
126707d5dec1SJeremy L Thompson 
126807d5dec1SJeremy L Thompson   @brief Get the number of points in the l-vector for a points CeedElemRestriction
126907d5dec1SJeremy L Thompson 
127007d5dec1SJeremy L Thompson   @param[in]  rstr       CeedElemRestriction
127107d5dec1SJeremy L Thompson   @param[out] num_points The number of points in the l-vector
127207d5dec1SJeremy L Thompson 
127307d5dec1SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
127407d5dec1SJeremy L Thompson 
1275*c63574e3SJeremy L Thompson   @ref User
127607d5dec1SJeremy L Thompson **/
127707d5dec1SJeremy L Thompson int CeedElemRestrictionGetNumPoints(CeedElemRestriction rstr, CeedInt *num_points) {
127807d5dec1SJeremy L Thompson   Ceed ceed;
127907d5dec1SJeremy L Thompson 
128007d5dec1SJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
128107d5dec1SJeremy L Thompson   CeedCheck(rstr->rstr_type == CEED_RESTRICTION_POINTS, ceed, CEED_ERROR_INCOMPATIBLE,
128207d5dec1SJeremy L Thompson             "Can only retrieve the number of points for a points CeedElemRestriction");
128307d5dec1SJeremy L Thompson 
128407d5dec1SJeremy L Thompson   *num_points = rstr->num_points;
128507d5dec1SJeremy L Thompson   return CEED_ERROR_SUCCESS;
128607d5dec1SJeremy L Thompson }
128707d5dec1SJeremy L Thompson 
128807d5dec1SJeremy L Thompson /**
128907d5dec1SJeremy L Thompson 
129007d5dec1SJeremy L Thompson   @brief Get the number of points in an element of a points CeedElemRestriction
129107d5dec1SJeremy L Thompson 
129207d5dec1SJeremy L Thompson   @param[in]  rstr       CeedElemRestriction
129307d5dec1SJeremy L Thompson   @param[in]  elem       Index number of element to retrieve the number of points for
129407d5dec1SJeremy L Thompson   @param[out] num_points The number of points in the element at index elem
129507d5dec1SJeremy L Thompson 
129607d5dec1SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
129707d5dec1SJeremy L Thompson 
1298*c63574e3SJeremy L Thompson   @ref User
129907d5dec1SJeremy L Thompson **/
130007d5dec1SJeremy L Thompson int CeedElemRestrictionGetNumPointsInElement(CeedElemRestriction rstr, CeedInt elem, CeedInt *num_points) {
130107d5dec1SJeremy L Thompson   Ceed           ceed;
130207d5dec1SJeremy L Thompson   const CeedInt *offsets;
130307d5dec1SJeremy L Thompson 
130407d5dec1SJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
130507d5dec1SJeremy L Thompson   CeedCheck(rstr->rstr_type == CEED_RESTRICTION_POINTS, ceed, CEED_ERROR_INCOMPATIBLE,
130607d5dec1SJeremy L Thompson             "Can only retrieve the number of points for a points CeedElemRestriction");
130707d5dec1SJeremy L Thompson 
130807d5dec1SJeremy L Thompson   CeedCall(CeedElemRestrictionGetOffsets(rstr, CEED_MEM_HOST, &offsets));
130907d5dec1SJeremy L Thompson   *num_points = offsets[elem + 1] - offsets[elem];
131007d5dec1SJeremy L Thompson   CeedCall(CeedElemRestrictionRestoreOffsets(rstr, &offsets));
131107d5dec1SJeremy L Thompson   return CEED_ERROR_SUCCESS;
131207d5dec1SJeremy L Thompson }
131307d5dec1SJeremy L Thompson 
131407d5dec1SJeremy L Thompson /**
13152c7e7413SJeremy L Thompson   @brief Get the maximum number of points in an element for a CeedElemRestriction at points
13162c7e7413SJeremy L Thompson 
13172c7e7413SJeremy L Thompson   @param[in]  rstr       CeedElemRestriction
13182c7e7413SJeremy L Thompson   @param[out] max_points Variable to store size of elements
13192c7e7413SJeremy L Thompson 
13202c7e7413SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
13212c7e7413SJeremy L Thompson 
13222c7e7413SJeremy L Thompson   @ref Advanced
13232c7e7413SJeremy L Thompson **/
13242c7e7413SJeremy L Thompson int CeedElemRestrictionGetMaxPointsInElement(CeedElemRestriction rstr, CeedInt *max_points) {
13252c7e7413SJeremy L Thompson   Ceed                ceed;
13262c7e7413SJeremy L Thompson   CeedInt             num_elem;
13272c7e7413SJeremy L Thompson   CeedRestrictionType rstr_type;
13282c7e7413SJeremy L Thompson 
13292c7e7413SJeremy L Thompson   CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed));
13302c7e7413SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
13312c7e7413SJeremy L Thompson   CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, ceed, CEED_ERROR_INCOMPATIBLE,
13322c7e7413SJeremy L Thompson             "Cannot compute max points for a CeedElemRestriction that does not use points");
13332c7e7413SJeremy L Thompson 
13342c7e7413SJeremy L Thompson   CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem));
13352c7e7413SJeremy L Thompson   *max_points = 0;
13362c7e7413SJeremy L Thompson   for (CeedInt e = 0; e < num_elem; e++) {
13372c7e7413SJeremy L Thompson     CeedInt num_points;
13382c7e7413SJeremy L Thompson 
13392c7e7413SJeremy L Thompson     CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, e, &num_points));
13402c7e7413SJeremy L Thompson     *max_points = CeedIntMax(num_points, *max_points);
13412c7e7413SJeremy L Thompson   }
1342e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1343a681ae63Sjeremylt }
1344a681ae63Sjeremylt 
1345a681ae63Sjeremylt /**
1346d979a051Sjeremylt   @brief Get the size of the l-vector for a CeedElemRestriction
1347a681ae63Sjeremylt 
1348ea61e9acSJeremy L Thompson   @param[in]  rstr   CeedElemRestriction
1349d1d35e2fSjeremylt   @param[out] l_size Variable to store number of nodes
1350a681ae63Sjeremylt 
1351a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1352a681ae63Sjeremylt 
1353b7c9bbdaSJeremy L Thompson   @ref Advanced
1354a681ae63Sjeremylt **/
13552b730f8bSJeremy L Thompson int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, CeedSize *l_size) {
1356d1d35e2fSjeremylt   *l_size = rstr->l_size;
1357e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1358a681ae63Sjeremylt }
1359a681ae63Sjeremylt 
1360a681ae63Sjeremylt /**
1361ea61e9acSJeremy L Thompson   @brief Get the number of components in the elements of a CeedElemRestriction
1362a681ae63Sjeremylt 
1363ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction
1364d1d35e2fSjeremylt   @param[out] num_comp Variable to store number of components
1365a681ae63Sjeremylt 
1366a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1367a681ae63Sjeremylt 
1368b7c9bbdaSJeremy L Thompson   @ref Advanced
1369a681ae63Sjeremylt **/
13702b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, CeedInt *num_comp) {
1371d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
1372e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1373a681ae63Sjeremylt }
1374a681ae63Sjeremylt 
1375a681ae63Sjeremylt /**
1376a681ae63Sjeremylt   @brief Get the number of blocks in a CeedElemRestriction
1377a681ae63Sjeremylt 
1378ea61e9acSJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
1379d1d35e2fSjeremylt   @param[out] num_block Variable to store number of blocks
1380a681ae63Sjeremylt 
1381a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1382a681ae63Sjeremylt 
1383b7c9bbdaSJeremy L Thompson   @ref Advanced
1384a681ae63Sjeremylt **/
13852b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, CeedInt *num_block) {
1386e7f679fcSJeremy L Thompson   *num_block = rstr->num_block;
1387e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1388a681ae63Sjeremylt }
1389a681ae63Sjeremylt 
1390a681ae63Sjeremylt /**
1391a681ae63Sjeremylt   @brief Get the size of blocks in the CeedElemRestriction
1392a681ae63Sjeremylt 
1393ea61e9acSJeremy L Thompson   @param[in]  rstr       CeedElemRestriction
1394e7f679fcSJeremy L Thompson   @param[out] block_size Variable to store size of blocks
1395a681ae63Sjeremylt 
1396a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1397a681ae63Sjeremylt 
1398b7c9bbdaSJeremy L Thompson   @ref Advanced
1399a681ae63Sjeremylt **/
1400e7f679fcSJeremy L Thompson int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, CeedInt *block_size) {
1401e7f679fcSJeremy L Thompson   *block_size = rstr->block_size;
1402e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1403a681ae63Sjeremylt }
1404a681ae63Sjeremylt 
1405a681ae63Sjeremylt /**
1406d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
14071469ee4dSjeremylt 
1408ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
1409d1d35e2fSjeremylt   @param[out] mult Vector to store multiplicity (of size l_size)
14101469ee4dSjeremylt 
14111469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
14121469ee4dSjeremylt 
14137a982d89SJeremy L. Thompson   @ref User
14141469ee4dSjeremylt **/
14152b730f8bSJeremy L Thompson int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, CeedVector mult) {
1416d1d35e2fSjeremylt   CeedVector e_vec;
14171469ee4dSjeremylt 
141825509ebbSRezgar Shakeri   // Create e_vec to hold intermediate computation in E^T (E 1)
14192b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionCreateVector(rstr, NULL, &e_vec));
14201469ee4dSjeremylt 
142125509ebbSRezgar Shakeri   // Compute e_vec = E * 1
14222b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 1.0));
14232b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, CEED_REQUEST_IMMEDIATE));
142425509ebbSRezgar Shakeri   // Compute multiplicity, mult = E^T * e_vec = E^T (E 1)
14252b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 0.0));
14262b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, CEED_REQUEST_IMMEDIATE));
14271469ee4dSjeremylt   // Cleanup
14282b730f8bSJeremy L Thompson   CeedCall(CeedVectorDestroy(&e_vec));
1429e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
14301469ee4dSjeremylt }
14311469ee4dSjeremylt 
14321469ee4dSjeremylt /**
1433f02ca4a2SJed Brown   @brief View a CeedElemRestriction
1434f02ca4a2SJed Brown 
1435f02ca4a2SJed Brown   @param[in] rstr   CeedElemRestriction to view
1436f02ca4a2SJed Brown   @param[in] stream Stream to write; typically stdout/stderr or a file
1437f02ca4a2SJed Brown 
1438f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
1439f02ca4a2SJed Brown 
14407a982d89SJeremy L. Thompson   @ref User
1441f02ca4a2SJed Brown **/
1442f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
14430930e4e7SJeremy L Thompson   CeedRestrictionType rstr_type;
14440930e4e7SJeremy L Thompson 
14450930e4e7SJeremy L Thompson   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
14460930e4e7SJeremy L Thompson 
14470930e4e7SJeremy L Thompson   if (rstr_type == CEED_RESTRICTION_POINTS) {
14480930e4e7SJeremy L Thompson     CeedInt max_points;
14490930e4e7SJeremy L Thompson 
14500930e4e7SJeremy L Thompson     CeedCall(CeedElemRestrictionGetMaxPointsInElement(rstr, &max_points));
14510930e4e7SJeremy L Thompson     fprintf(stream,
14520930e4e7SJeremy L Thompson             "CeedElemRestriction at points from (%td, %" CeedInt_FMT ") to %" CeedInt_FMT " elements with a maximum of %" CeedInt_FMT
14530930e4e7SJeremy L Thompson             " points on an element\n",
14540930e4e7SJeremy L Thompson             rstr->l_size, rstr->num_comp, rstr->num_elem, max_points);
14550930e4e7SJeremy L Thompson   } else {
14567509a596Sjeremylt     char stridesstr[500];
14571c66c397SJeremy L Thompson 
14582b730f8bSJeremy L Thompson     if (rstr->strides) {
14592b730f8bSJeremy L Thompson       sprintf(stridesstr, "[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "]", rstr->strides[0], rstr->strides[1], rstr->strides[2]);
14602b730f8bSJeremy L Thompson     } else {
1461990fdeb6SJeremy L Thompson       sprintf(stridesstr, "%" CeedInt_FMT, rstr->comp_stride);
14622b730f8bSJeremy L Thompson     }
14632b730f8bSJeremy L Thompson     fprintf(stream, "%sCeedElemRestriction from (%td, %" CeedInt_FMT ") to %" CeedInt_FMT " elements with %" CeedInt_FMT " nodes each and %s %s\n",
1464e7f679fcSJeremy L Thompson             rstr->block_size > 1 ? "Blocked " : "", rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
1465d979a051Sjeremylt             rstr->strides ? "strides" : "component stride", stridesstr);
14660930e4e7SJeremy L Thompson   }
1467e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1468f02ca4a2SJed Brown }
1469f02ca4a2SJed Brown 
1470f02ca4a2SJed Brown /**
1471b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
1472b11c1e72Sjeremylt 
1473ea61e9acSJeremy L Thompson   @param[in,out] rstr CeedElemRestriction to destroy
1474b11c1e72Sjeremylt 
1475b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1476dfdf5a53Sjeremylt 
14777a982d89SJeremy L. Thompson   @ref User
1478b11c1e72Sjeremylt **/
14794ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
1480393ac2cdSJeremy L Thompson   if (!*rstr || *rstr == CEED_ELEMRESTRICTION_NONE || --(*rstr)->ref_count > 0) {
1481ad6481ceSJeremy L Thompson     *rstr = NULL;
1482ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
1483ad6481ceSJeremy L Thompson   }
14846574a04fSJeremy L Thompson   CeedCheck((*rstr)->num_readers == 0, (*rstr)->ceed, CEED_ERROR_ACCESS,
14856574a04fSJeremy L Thompson             "Cannot destroy CeedElemRestriction, a process has read access to the offset data");
1486c17ec2beSJeremy L Thompson 
1487c17ec2beSJeremy L Thompson   // Only destroy backend data once between rstr and unsigned copy
14887c1dbaffSSebastian Grimberg   if ((*rstr)->rstr_base) CeedCall(CeedElemRestrictionDestroy(&(*rstr)->rstr_base));
1489c17ec2beSJeremy L Thompson   else if ((*rstr)->Destroy) CeedCall((*rstr)->Destroy(*rstr));
1490c17ec2beSJeremy L Thompson 
14912b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*rstr)->strides));
14922b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*rstr)->ceed));
14932b730f8bSJeremy L Thompson   CeedCall(CeedFree(rstr));
1494e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1495d7b241e6Sjeremylt }
1496d7b241e6Sjeremylt 
1497d7b241e6Sjeremylt /// @}
1498