xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-elemrestriction.c (revision 49aac155e7a09736f56fb3abac0f57dab29f7cbf)
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>
9*49aac155SJeremy L Thompson #include <ceed.h>
102b730f8bSJeremy L Thompson #include <ceed/backend.h>
113d576824SJeremy L Thompson #include <stdbool.h>
123d576824SJeremy L Thompson #include <stdio.h>
13d7b241e6Sjeremylt 
147a982d89SJeremy L. Thompson /// @file
157a982d89SJeremy L. Thompson /// Implementation of CeedElemRestriction interfaces
167a982d89SJeremy L. Thompson 
177a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
187a982d89SJeremy L. Thompson /// CeedElemRestriction Library Internal Functions
197a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
207a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionDeveloper
217a982d89SJeremy L. Thompson /// @{
227a982d89SJeremy L. Thompson 
237a982d89SJeremy L. Thompson /**
24d979a051Sjeremylt   @brief Permute and pad offsets for a blocked restriction
257a982d89SJeremy L. Thompson 
26ea61e9acSJeremy L Thompson   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
27ea61e9acSJeremy L Thompson                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
28ea61e9acSJeremy L Thompson 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
29ea61e9acSJeremy L Thompson   @param[out] blk_offsets Array of permuted and padded offsets of shape [@a num_blk, @a elem_size, @a blk_size].
30ea61e9acSJeremy L Thompson   @param[in]  num_blk     Number of blocks
31ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements
32ea61e9acSJeremy L Thompson   @param[in]  blk_size    Number of elements in a block
33ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size of each element
347a982d89SJeremy L. Thompson 
357a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
367a982d89SJeremy L. Thompson 
377a982d89SJeremy L. Thompson   @ref Utility
387a982d89SJeremy L. Thompson **/
392b730f8bSJeremy L Thompson int CeedPermutePadOffsets(const CeedInt *offsets, CeedInt *blk_offsets, CeedInt num_blk, CeedInt num_elem, CeedInt blk_size, CeedInt elem_size) {
402b730f8bSJeremy L Thompson   for (CeedInt e = 0; e < num_blk * blk_size; e += blk_size) {
412b730f8bSJeremy L Thompson     for (CeedInt j = 0; j < blk_size; j++) {
422b730f8bSJeremy L Thompson       for (CeedInt k = 0; k < elem_size; k++) {
432b730f8bSJeremy L Thompson         blk_offsets[e * elem_size + k * blk_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 
507a982d89SJeremy L. Thompson /// @}
517a982d89SJeremy L. Thompson 
527a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
537a982d89SJeremy L. Thompson /// CeedElemRestriction Backend API
547a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
557a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionBackend
567a982d89SJeremy L. Thompson /// @{
577a982d89SJeremy L. Thompson 
587a982d89SJeremy L. Thompson /**
59a681ae63Sjeremylt 
60a681ae63Sjeremylt   @brief Get the strides of a strided CeedElemRestriction
617a982d89SJeremy L. Thompson 
62ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
63a681ae63Sjeremylt   @param[out] strides Variable to store strides array
647a982d89SJeremy L. Thompson 
657a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
667a982d89SJeremy L. Thompson 
677a982d89SJeremy L. Thompson   @ref Backend
687a982d89SJeremy L. Thompson **/
692b730f8bSJeremy L Thompson int CeedElemRestrictionGetStrides(CeedElemRestriction rstr, CeedInt (*strides)[3]) {
702b730f8bSJeremy L Thompson   if (!rstr->strides) {
71a681ae63Sjeremylt     // LCOV_EXCL_START
722b730f8bSJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
73a681ae63Sjeremylt     // LCOV_EXCL_STOP
742b730f8bSJeremy L Thompson   }
75a681ae63Sjeremylt 
762b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*strides)[i] = rstr->strides[i];
77e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
787a982d89SJeremy L. Thompson }
797a982d89SJeremy L. Thompson 
807a982d89SJeremy L. Thompson /**
81bd33150aSjeremylt   @brief Get read-only access to a CeedElemRestriction offsets array by memtype
82bd33150aSjeremylt 
83ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction to retrieve offsets
84ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the array.
85ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy (possibly cached).
86d1d35e2fSjeremylt   @param[out] offsets Array on memory type mem_type
87bd33150aSjeremylt 
88bd33150aSjeremylt   @return An error code: 0 - success, otherwise - failure
89bd33150aSjeremylt 
90bd33150aSjeremylt   @ref User
91bd33150aSjeremylt **/
922b730f8bSJeremy L Thompson int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) {
932b730f8bSJeremy L Thompson   if (!rstr->GetOffsets) {
94bd33150aSjeremylt     // LCOV_EXCL_START
952b730f8bSJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetOffsets");
96bd33150aSjeremylt     // LCOV_EXCL_STOP
972b730f8bSJeremy L Thompson   }
98bd33150aSjeremylt 
992b730f8bSJeremy L Thompson   CeedCall(rstr->GetOffsets(rstr, mem_type, offsets));
100d1d35e2fSjeremylt   rstr->num_readers++;
101e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
102430758c8SJeremy L Thompson }
103430758c8SJeremy L Thompson 
104430758c8SJeremy L Thompson /**
105430758c8SJeremy L Thompson   @brief Restore an offsets array obtained using CeedElemRestrictionGetOffsets()
106430758c8SJeremy L Thompson 
107ea61e9acSJeremy L Thompson   @param[in] rstr    CeedElemRestriction to restore
108ea61e9acSJeremy L Thompson   @param[in] offsets Array of offset data
109430758c8SJeremy L Thompson 
110430758c8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
111430758c8SJeremy L Thompson 
112430758c8SJeremy L Thompson   @ref User
113430758c8SJeremy L Thompson **/
1142b730f8bSJeremy L Thompson int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr, const CeedInt **offsets) {
115430758c8SJeremy L Thompson   *offsets = NULL;
116d1d35e2fSjeremylt   rstr->num_readers--;
117e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
118bd33150aSjeremylt }
119bd33150aSjeremylt 
120bd33150aSjeremylt /**
1213ac43b2cSJeremy L Thompson   @brief Get the strided status of a CeedElemRestriction
1223ac43b2cSJeremy L Thompson 
123ea61e9acSJeremy L Thompson   @param[in]  rstr        CeedElemRestriction
124d1d35e2fSjeremylt   @param[out] is_strided  Variable to store strided status, 1 if strided else 0
1253ac43b2cSJeremy L Thompson 
1263ac43b2cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1273ac43b2cSJeremy L Thompson 
1283ac43b2cSJeremy L Thompson   @ref Backend
1293ac43b2cSJeremy L Thompson **/
130d1d35e2fSjeremylt int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) {
131d1d35e2fSjeremylt   *is_strided = rstr->strides ? true : false;
132e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1333ac43b2cSJeremy L Thompson }
1343ac43b2cSJeremy L Thompson 
1353ac43b2cSJeremy L Thompson /**
136b435c5a6Srezgarshakeri   @brief Get oriented status of a CeedElemRestriction
137b435c5a6Srezgarshakeri 
138ea61e9acSJeremy L Thompson   @param[in]  rstr         CeedElemRestriction
139b435c5a6Srezgarshakeri   @param[out] is_oriented  Variable to store oriented status, 1 if oriented else 0
140b435c5a6Srezgarshakeri 
141b435c5a6Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
142b435c5a6Srezgarshakeri 
143b435c5a6Srezgarshakeri   @ref Backend
144b435c5a6Srezgarshakeri **/
145b435c5a6Srezgarshakeri int CeedElemRestrictionIsOriented(CeedElemRestriction rstr, bool *is_oriented) {
146b435c5a6Srezgarshakeri   *is_oriented = rstr->is_oriented;
147b435c5a6Srezgarshakeri   return CEED_ERROR_SUCCESS;
148b435c5a6Srezgarshakeri }
149b435c5a6Srezgarshakeri 
150b435c5a6Srezgarshakeri /**
151a681ae63Sjeremylt   @brief Get the backend stride status of a CeedElemRestriction
1527a982d89SJeremy L. Thompson 
153ea61e9acSJeremy L Thompson   @param[in]  rstr                 CeedElemRestriction
15496b902e2Sjeremylt   @param[out] has_backend_strides  Variable to store stride status
1557a982d89SJeremy L. Thompson 
1567a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1577a982d89SJeremy L. Thompson 
1587a982d89SJeremy L. Thompson   @ref Backend
1597a982d89SJeremy L. Thompson **/
1602b730f8bSJeremy L Thompson int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, bool *has_backend_strides) {
1612b730f8bSJeremy L Thompson   if (!rstr->strides) {
162a681ae63Sjeremylt     // LCOV_EXCL_START
1632b730f8bSJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
164a681ae63Sjeremylt     // LCOV_EXCL_STOP
1652b730f8bSJeremy L Thompson   }
1667a982d89SJeremy L. Thompson 
1672b730f8bSJeremy L Thompson   *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
168a681ae63Sjeremylt                           (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
169e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1707a982d89SJeremy L. Thompson }
1717a982d89SJeremy L. Thompson 
1727a982d89SJeremy L. Thompson /**
17349fd234cSJeremy L Thompson 
17449fd234cSJeremy L Thompson   @brief Get the E-vector layout of a CeedElemRestriction
17549fd234cSJeremy L Thompson 
176ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
177ea61e9acSJeremy L Thompson   @param[out] layout  Variable to store layout array, stored as [nodes, components, elements].
178ea61e9acSJeremy 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]
17949fd234cSJeremy L Thompson 
18049fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
18149fd234cSJeremy L Thompson 
18249fd234cSJeremy L Thompson   @ref Backend
18349fd234cSJeremy L Thompson **/
1842b730f8bSJeremy L Thompson int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, CeedInt (*layout)[3]) {
1852b730f8bSJeremy L Thompson   if (!rstr->layout[0]) {
18649fd234cSJeremy L Thompson     // LCOV_EXCL_START
1872b730f8bSJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no layout data");
18849fd234cSJeremy L Thompson     // LCOV_EXCL_STOP
1892b730f8bSJeremy L Thompson   }
19049fd234cSJeremy L Thompson 
1912b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*layout)[i] = rstr->layout[i];
192e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
19349fd234cSJeremy L Thompson }
19449fd234cSJeremy L Thompson 
19549fd234cSJeremy L Thompson /**
19649fd234cSJeremy L Thompson 
19749fd234cSJeremy L Thompson   @brief Set the E-vector layout of a CeedElemRestriction
19849fd234cSJeremy L Thompson 
199ea61e9acSJeremy L Thompson   @param[in] rstr   CeedElemRestriction
200ea61e9acSJeremy L Thompson   @param[in] layout Variable to containing layout array, stored as [nodes, components, elements].
201ea61e9acSJeremy 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]
20249fd234cSJeremy L Thompson 
20349fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
20449fd234cSJeremy L Thompson 
20549fd234cSJeremy L Thompson   @ref Backend
20649fd234cSJeremy L Thompson **/
2072b730f8bSJeremy L Thompson int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
2082b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) rstr->layout[i] = layout[i];
209e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
21049fd234cSJeremy L Thompson }
21149fd234cSJeremy L Thompson 
21249fd234cSJeremy L Thompson /**
2137a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedElemRestriction
2147a982d89SJeremy L. Thompson 
215ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
2167a982d89SJeremy L. Thompson   @param[out] data Variable to store data
2177a982d89SJeremy L. Thompson 
2187a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2197a982d89SJeremy L. Thompson 
2207a982d89SJeremy L. Thompson   @ref Backend
2217a982d89SJeremy L. Thompson **/
222777ff853SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) {
223777ff853SJeremy L Thompson   *(void **)data = rstr->data;
224e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2257a982d89SJeremy L. Thompson }
2267a982d89SJeremy L. Thompson 
2277a982d89SJeremy L. Thompson /**
2287a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedElemRestriction
2297a982d89SJeremy L. Thompson 
230ea61e9acSJeremy L Thompson   @param[in,out] rstr CeedElemRestriction
231ea61e9acSJeremy L Thompson   @param[in]     data Data to set
2327a982d89SJeremy L. Thompson 
2337a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2347a982d89SJeremy L. Thompson 
2357a982d89SJeremy L. Thompson   @ref Backend
2367a982d89SJeremy L. Thompson **/
237777ff853SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) {
238777ff853SJeremy L Thompson   rstr->data = data;
239e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2407a982d89SJeremy L. Thompson }
2417a982d89SJeremy L. Thompson 
24234359f16Sjeremylt /**
24334359f16Sjeremylt   @brief Increment the reference counter for a CeedElemRestriction
24434359f16Sjeremylt 
245ea61e9acSJeremy L Thompson   @param[in,out] rstr ElemRestriction to increment the reference counter
24634359f16Sjeremylt 
24734359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
24834359f16Sjeremylt 
24934359f16Sjeremylt   @ref Backend
25034359f16Sjeremylt **/
2519560d06aSjeremylt int CeedElemRestrictionReference(CeedElemRestriction rstr) {
25234359f16Sjeremylt   rstr->ref_count++;
25334359f16Sjeremylt   return CEED_ERROR_SUCCESS;
25434359f16Sjeremylt }
25534359f16Sjeremylt 
2566e15d496SJeremy L Thompson /**
2576e15d496SJeremy L Thompson   @brief Estimate number of FLOPs required to apply CeedElemRestriction in t_mode
2586e15d496SJeremy L Thompson 
259ea61e9acSJeremy L Thompson   @param[in]  rstr   ElemRestriction to estimate FLOPs for
260ea61e9acSJeremy L Thompson   @param[in]  t_mode Apply restriction or transpose
261ea61e9acSJeremy L Thompson   @param[out] flops  Address of variable to hold FLOPs estimate
2626e15d496SJeremy L Thompson 
2636e15d496SJeremy L Thompson   @ref Backend
2646e15d496SJeremy L Thompson **/
2652b730f8bSJeremy L Thompson int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedSize *flops) {
2666e15d496SJeremy L Thompson   bool    is_oriented;
2672b730f8bSJeremy L Thompson   CeedInt e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp, scale = 0;
2686e15d496SJeremy L Thompson 
2692b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionIsOriented(rstr, &is_oriented));
2706e15d496SJeremy L Thompson   switch (t_mode) {
2712b730f8bSJeremy L Thompson     case CEED_NOTRANSPOSE:
2722b730f8bSJeremy L Thompson       scale = is_oriented ? 1 : 0;
2732b730f8bSJeremy L Thompson       break;
2742b730f8bSJeremy L Thompson     case CEED_TRANSPOSE:
2752b730f8bSJeremy L Thompson       scale = is_oriented ? 2 : 1;
2762b730f8bSJeremy L Thompson       break;
2776e15d496SJeremy L Thompson   }
2786e15d496SJeremy L Thompson   *flops = e_size * scale;
2796e15d496SJeremy L Thompson 
2806e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2816e15d496SJeremy L Thompson }
2826e15d496SJeremy L Thompson 
2837a982d89SJeremy L. Thompson /// @}
2847a982d89SJeremy L. Thompson 
28515910d16Sjeremylt /// @cond DOXYGEN_SKIP
28615910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
28715910d16Sjeremylt /// @endcond
28815910d16Sjeremylt 
2897a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
2907a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
2917a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
2927a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
293d7b241e6Sjeremylt /// @{
294d7b241e6Sjeremylt 
2957a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
29645f1e315Sjeremylt const CeedInt CEED_STRIDES_BACKEND[3] = {0};
2977a982d89SJeremy L. Thompson 
2984cc79fe7SJed Brown /// Indicate that no CeedElemRestriction is provided by the user
2992b730f8bSJeremy L Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = &ceed_elemrestriction_none;
3007a982d89SJeremy L. Thompson 
301d7b241e6Sjeremylt /**
302b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
303d7b241e6Sjeremylt 
304ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
305ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array
306ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
307ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
308ea61e9acSJeremy L Thompson   @param[in]  comp_stride Stride between components for the same L-vector "node".
309ea61e9acSJeremy L Thompson                             Data for node i, component j, element k can be found in the L-vector at index offsets[i + k*elem_size] + j*comp_stride.
310ea61e9acSJeremy L Thompson   @param[in]  l_size      The size of the L-vector.
311ea61e9acSJeremy L Thompson                             This vector may be larger than the elements and fields given by this restriction.
312ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
313ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
314ea61e9acSJeremy L Thompson   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
315ea61e9acSJeremy L Thompson                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
316ea61e9acSJeremy L Thompson 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
317ea61e9acSJeremy L Thompson   @param[out] rstr    Address of the variable where the newly created CeedElemRestriction will be stored
318d7b241e6Sjeremylt 
319b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
320dfdf5a53Sjeremylt 
3217a982d89SJeremy L. Thompson   @ref User
322b11c1e72Sjeremylt **/
3232b730f8bSJeremy L Thompson int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
3242b730f8bSJeremy L Thompson                               CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
3255fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
3265fe0d4faSjeremylt     Ceed delegate;
3272b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
3285fe0d4faSjeremylt 
3292b730f8bSJeremy L Thompson     if (!delegate) {
330c042f62fSJeremy L Thompson       // LCOV_EXCL_START
3312b730f8bSJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ElemRestrictionCreate");
332c042f62fSJeremy L Thompson       // LCOV_EXCL_STOP
3332b730f8bSJeremy L Thompson     }
3345fe0d4faSjeremylt 
3352b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
336e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
3375fe0d4faSjeremylt   }
3385fe0d4faSjeremylt 
3392b730f8bSJeremy L Thompson   if (elem_size < 1) {
340e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
3412b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
342e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
3432b730f8bSJeremy L Thompson   }
344e022e1f8SJeremy L Thompson 
3452b730f8bSJeremy L Thompson   if (num_comp < 1) {
346e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
3472b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
348e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
3492b730f8bSJeremy L Thompson   }
350e022e1f8SJeremy L Thompson 
3512b730f8bSJeremy L Thompson   if (num_comp > 1 && comp_stride < 1) {
352e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
3532b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
354e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
3552b730f8bSJeremy L Thompson   }
356e022e1f8SJeremy L Thompson 
3572b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
3584ce2993fSjeremylt   (*rstr)->ceed = ceed;
3592b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
360d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
361d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
362d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
363d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
364d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
365d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
366d1d35e2fSjeremylt   (*rstr)->num_blk     = num_elem;
367d1d35e2fSjeremylt   (*rstr)->blk_size    = 1;
368b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 0;
3692b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, *rstr));
370e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
371d7b241e6Sjeremylt }
372d7b241e6Sjeremylt 
373d7b241e6Sjeremylt /**
374fc0567d9Srezgarshakeri   @brief Create a CeedElemRestriction with orientation sign
375fc0567d9Srezgarshakeri 
376ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
377ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array
378ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
379ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
380ea61e9acSJeremy L Thompson   @param[in]  comp_stride Stride between components for the same L-vector "node".
381ea61e9acSJeremy L Thompson                             Data for node i, component j, element k can be found in the L-vector at index offsets[i + k*elem_size] + j*comp_stride.
382ea61e9acSJeremy L Thompson   @param[in]  l_size      The size of the L-vector.
383ea61e9acSJeremy L Thompson                             This vector may be larger than the elements and fields given by this restriction.
384ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
385ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
386ea61e9acSJeremy L Thompson   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
387ea61e9acSJeremy L Thompson                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
388ea61e9acSJeremy L Thompson 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
389ea61e9acSJeremy L Thompson   @param[in]  orient      Array of shape [@a num_elem, @a elem_size] with bool false for positively oriented and true to flip the orientation.
390ea61e9acSJeremy L Thompson   @param[out] rstr       Address of the variable where the newly created CeedElemRestriction will be stored
391fc0567d9Srezgarshakeri 
392fc0567d9Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
393fc0567d9Srezgarshakeri 
394fc0567d9Srezgarshakeri   @ref User
395fc0567d9Srezgarshakeri **/
3962b730f8bSJeremy L Thompson int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
3972b730f8bSJeremy L Thompson                                       CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orient,
398fc0567d9Srezgarshakeri                                       CeedElemRestriction *rstr) {
399c7745053SRezgar Shakeri   if (!ceed->ElemRestrictionCreateOriented) {
400fc0567d9Srezgarshakeri     Ceed delegate;
4012b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
402fc0567d9Srezgarshakeri 
4032b730f8bSJeremy L Thompson     if (!delegate) {
404fc0567d9Srezgarshakeri       // LCOV_EXCL_START
4052b730f8bSJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateOriented");
406fc0567d9Srezgarshakeri       // LCOV_EXCL_STOP
4072b730f8bSJeremy L Thompson     }
408fc0567d9Srezgarshakeri 
4092b730f8bSJeremy L Thompson     CeedCall(
4102b730f8bSJeremy L Thompson         CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, orient, rstr));
411fc0567d9Srezgarshakeri     return CEED_ERROR_SUCCESS;
412fc0567d9Srezgarshakeri   }
413fc0567d9Srezgarshakeri 
4142b730f8bSJeremy L Thompson   if (elem_size < 1) {
415e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
4162b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
417e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
4182b730f8bSJeremy L Thompson   }
419e022e1f8SJeremy L Thompson 
4202b730f8bSJeremy L Thompson   if (num_comp < 1) {
421e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
4222b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
423e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
4242b730f8bSJeremy L Thompson   }
425e022e1f8SJeremy L Thompson 
4262b730f8bSJeremy L Thompson   if (num_comp > 1 && comp_stride < 1) {
427e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
4282b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
429e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
4302b730f8bSJeremy L Thompson   }
431e022e1f8SJeremy L Thompson 
4322b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
433fc0567d9Srezgarshakeri   (*rstr)->ceed = ceed;
4342b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
435fc0567d9Srezgarshakeri   (*rstr)->ref_count   = 1;
436fc0567d9Srezgarshakeri   (*rstr)->num_elem    = num_elem;
437fc0567d9Srezgarshakeri   (*rstr)->elem_size   = elem_size;
438fc0567d9Srezgarshakeri   (*rstr)->num_comp    = num_comp;
439fc0567d9Srezgarshakeri   (*rstr)->comp_stride = comp_stride;
440fc0567d9Srezgarshakeri   (*rstr)->l_size      = l_size;
441fc0567d9Srezgarshakeri   (*rstr)->num_blk     = num_elem;
442fc0567d9Srezgarshakeri   (*rstr)->blk_size    = 1;
443b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 1;
4442b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateOriented(mem_type, copy_mode, offsets, orient, *rstr));
445fc0567d9Srezgarshakeri   return CEED_ERROR_SUCCESS;
446fc0567d9Srezgarshakeri }
447fc0567d9Srezgarshakeri 
448fc0567d9Srezgarshakeri /**
4497509a596Sjeremylt   @brief Create a strided CeedElemRestriction
450d7b241e6Sjeremylt 
451ea61e9acSJeremy L Thompson   @param[in]  ceed      Ceed object where the CeedElemRestriction will be created
452ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
453ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
454ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation "node" (1 for scalar fields)
455ea61e9acSJeremy L Thompson   @param[in]  l_size    The size of the L-vector.
456ea61e9acSJeremy L Thompson                           This vector may be larger than the elements and fields given by this restriction.
457ea61e9acSJeremy L Thompson   @param[in]  strides   Array for strides between [nodes, components, elements].
458ea61e9acSJeremy L Thompson                           Data for node i, component j, element k can be found in the L-vector at index i*strides[0] + j*strides[1] + k*strides[2].
459ea61e9acSJeremy L Thompson                           @a CEED_STRIDES_BACKEND may be used with vectors created by a Ceed backend.
460ea61e9acSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created CeedElemRestriction will be stored
461d7b241e6Sjeremylt 
462b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
463dfdf5a53Sjeremylt 
4647a982d89SJeremy L. Thompson   @ref User
465b11c1e72Sjeremylt **/
4662b730f8bSJeremy L Thompson int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedSize l_size, const CeedInt strides[3],
467f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
4685fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
4695fe0d4faSjeremylt     Ceed delegate;
4702b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
4715fe0d4faSjeremylt 
4722b730f8bSJeremy L Thompson     if (!delegate) {
473c042f62fSJeremy L Thompson       // LCOV_EXCL_START
4742b730f8bSJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ElemRestrictionCreate");
475c042f62fSJeremy L Thompson       // LCOV_EXCL_STOP
4762b730f8bSJeremy L Thompson     }
4775fe0d4faSjeremylt 
4782b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, l_size, strides, rstr));
479e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
4805fe0d4faSjeremylt   }
4815fe0d4faSjeremylt 
4822b730f8bSJeremy L Thompson   if (elem_size < 1) {
483e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
4842b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
485e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
4862b730f8bSJeremy L Thompson   }
487e022e1f8SJeremy L Thompson 
4882b730f8bSJeremy L Thompson   if (num_comp < 1) {
489e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
4902b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
491e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
4922b730f8bSJeremy L Thompson   }
493e022e1f8SJeremy L Thompson 
4942b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
4954ce2993fSjeremylt   (*rstr)->ceed = ceed;
4962b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
497d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
498d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
499d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
500d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
501d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
502d1d35e2fSjeremylt   (*rstr)->num_blk     = num_elem;
503d1d35e2fSjeremylt   (*rstr)->blk_size    = 1;
504b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 0;
5052b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
5062b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
5072b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, *rstr));
508e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
509d7b241e6Sjeremylt }
510d7b241e6Sjeremylt 
511d7b241e6Sjeremylt /**
512b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
513d7b241e6Sjeremylt 
514ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created.
515ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array.
516ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of unknowns) per element
517ea61e9acSJeremy L Thompson   @param[in]  blk_size    Number of elements in a block
518ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
519ea61e9acSJeremy L Thompson   @param[in]  comp_stride Stride between components for the same L-vector "node".
520ea61e9acSJeremy L Thompson                             Data for node i, component j, element k can be found in the L-vector at index offsets[i + k*elem_size] + j*comp_stride.
521ea61e9acSJeremy L Thompson   @param[in]  l_size      The size of the L-vector.
522ea61e9acSJeremy L Thompson                             This vector may be larger than the elements and fields given by this restriction.
523ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
524ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
525ea61e9acSJeremy L Thompson   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
526ea61e9acSJeremy L Thompson                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
527ea61e9acSJeremy L Thompson  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
528ea61e9acSJeremy L Thompson  the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
529ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
530d7b241e6Sjeremylt 
531b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
532dfdf5a53Sjeremylt 
5337a982d89SJeremy L. Thompson   @ref Backend
534b11c1e72Sjeremylt  **/
5352b730f8bSJeremy L Thompson int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedInt comp_stride,
5362b730f8bSJeremy L Thompson                                      CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets,
5374ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
538d1d35e2fSjeremylt   CeedInt *blk_offsets;
539d1d35e2fSjeremylt   CeedInt  num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
540d7b241e6Sjeremylt 
5415fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
5425fe0d4faSjeremylt     Ceed delegate;
5432b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
5445fe0d4faSjeremylt 
5452b730f8bSJeremy L Thompson     if (!delegate) {
546c042f62fSJeremy L Thompson       // LCOV_EXCL_START
5472b730f8bSJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ElemRestrictionCreateBlocked");
548c042f62fSJeremy L Thompson       // LCOV_EXCL_STOP
5492b730f8bSJeremy L Thompson     }
5505fe0d4faSjeremylt 
5512b730f8bSJeremy L Thompson     CeedCall(
5522b730f8bSJeremy L Thompson         CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, blk_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
553e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
5545fe0d4faSjeremylt   }
555d7b241e6Sjeremylt 
5562b730f8bSJeremy L Thompson   if (elem_size < 1) {
557e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
5582b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
559e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
5602b730f8bSJeremy L Thompson   }
561e022e1f8SJeremy L Thompson 
5622b730f8bSJeremy L Thompson   if (blk_size < 1) {
563e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
5642b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
565e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
5662b730f8bSJeremy L Thompson   }
567e022e1f8SJeremy L Thompson 
5682b730f8bSJeremy L Thompson   if (num_comp < 1) {
569e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
5702b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
571e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
5722b730f8bSJeremy L Thompson   }
573e022e1f8SJeremy L Thompson 
5742b730f8bSJeremy L Thompson   if (num_comp > 1 && comp_stride < 1) {
575e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
5762b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
577e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
5782b730f8bSJeremy L Thompson   }
579e022e1f8SJeremy L Thompson 
5802b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
581d7b241e6Sjeremylt 
5822b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(num_blk * blk_size * elem_size, &blk_offsets));
5832b730f8bSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size, elem_size));
584d7b241e6Sjeremylt 
5854ce2993fSjeremylt   (*rstr)->ceed = ceed;
5862b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
587d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
588d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
589d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
590d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
591d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
592d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
593d1d35e2fSjeremylt   (*rstr)->num_blk     = num_blk;
594d1d35e2fSjeremylt   (*rstr)->blk_size    = blk_size;
595b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 0;
5962b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)blk_offsets, *rstr));
597d1d35e2fSjeremylt   if (copy_mode == CEED_OWN_POINTER) {
5982b730f8bSJeremy L Thompson     CeedCall(CeedFree(&offsets));
5991d102b48SJeremy L Thompson   }
600e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
601d7b241e6Sjeremylt }
602d7b241e6Sjeremylt 
603b11c1e72Sjeremylt /**
6047509a596Sjeremylt   @brief Create a blocked strided CeedElemRestriction
6057509a596Sjeremylt 
606ea61e9acSJeremy L Thompson   @param[in]  ceed      Ceed object where the CeedElemRestriction will be created
607ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
608ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
609ea61e9acSJeremy L Thompson   @param[in]  blk_size  Number of elements in a block
610ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation node (1 for scalar fields)
611ea61e9acSJeremy L Thompson   @param[in]  l_size    The size of the L-vector.
612ea61e9acSJeremy L Thompson                           This vector may be larger than the elements and fields given by this restriction.
613ea61e9acSJeremy L Thompson   @param[in]  strides   Array for strides between [nodes, components, elements].
614ea61e9acSJeremy L Thompson                           Data for node i, component j, element k can be found in the L-vector at index i*strides[0] + j*strides[1] + k*strides[2].
615ea61e9acSJeremy L Thompson                           @a CEED_STRIDES_BACKEND may be used with vectors created by a Ceed backend.
616ea61e9acSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created CeedElemRestriction will be stored
6177509a596Sjeremylt 
6187509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
6197509a596Sjeremylt 
6207a982d89SJeremy L. Thompson   @ref User
6217509a596Sjeremylt **/
6222b730f8bSJeremy L Thompson int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedSize l_size,
6238621c6c6SJeremy L Thompson                                             const CeedInt strides[3], CeedElemRestriction *rstr) {
624d1d35e2fSjeremylt   CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
6257509a596Sjeremylt 
6267509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
6277509a596Sjeremylt     Ceed delegate;
6282b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
6297509a596Sjeremylt 
6302b730f8bSJeremy L Thompson     if (!delegate) {
6317509a596Sjeremylt       // LCOV_EXCL_START
6322b730f8bSJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ElemRestrictionCreateBlocked");
6337509a596Sjeremylt       // LCOV_EXCL_STOP
6342b730f8bSJeremy L Thompson     }
6357509a596Sjeremylt 
6362b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, blk_size, num_comp, l_size, strides, rstr));
637e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6387509a596Sjeremylt   }
6397509a596Sjeremylt 
6402b730f8bSJeremy L Thompson   if (elem_size < 1) {
641e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
6422b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
643e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
6442b730f8bSJeremy L Thompson   }
645e022e1f8SJeremy L Thompson 
6462b730f8bSJeremy L Thompson   if (blk_size < 1) {
647e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
6482b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
649e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
6502b730f8bSJeremy L Thompson   }
651e022e1f8SJeremy L Thompson 
6522b730f8bSJeremy L Thompson   if (num_comp < 1) {
653e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
6542b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
655e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
6562b730f8bSJeremy L Thompson   }
657e022e1f8SJeremy L Thompson 
6582b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
6597509a596Sjeremylt 
6607509a596Sjeremylt   (*rstr)->ceed = ceed;
6612b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
662d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
663d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
664d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
665d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
666d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
667d1d35e2fSjeremylt   (*rstr)->num_blk     = num_blk;
668d1d35e2fSjeremylt   (*rstr)->blk_size    = blk_size;
669b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 0;
6702b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
6712b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
6722b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, *rstr));
673e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6747509a596Sjeremylt }
6757509a596Sjeremylt 
6767509a596Sjeremylt /**
677ea61e9acSJeremy L Thompson   @brief Copy the pointer to a CeedElemRestriction.
678ea61e9acSJeremy L Thompson            Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
6799560d06aSjeremylt 
680512bb800SJeremy L Thompson            Note: If the value of `rstr_copy` passed into this function is non-NULL, then it is assumed that `rstr_copy` is a pointer to a
681512bb800SJeremy L Thompson              CeedElemRestriction. This CeedElemRestriction will be destroyed if `rstr_copy` is the only reference to this CeedElemRestriction.
682ea61e9acSJeremy L Thompson 
683ea61e9acSJeremy L Thompson   @param[in]     rstr      CeedElemRestriction to copy reference to
684ea61e9acSJeremy L Thompson   @param[in,out] rstr_copy Variable to store copied reference
6859560d06aSjeremylt 
6869560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
6879560d06aSjeremylt 
6889560d06aSjeremylt   @ref User
6899560d06aSjeremylt **/
6902b730f8bSJeremy L Thompson int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_copy) {
6912b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionReference(rstr));
6922b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionDestroy(rstr_copy));
6939560d06aSjeremylt   *rstr_copy = rstr;
6949560d06aSjeremylt   return CEED_ERROR_SUCCESS;
6959560d06aSjeremylt }
6969560d06aSjeremylt 
6979560d06aSjeremylt /**
698b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
699b11c1e72Sjeremylt 
700ea61e9acSJeremy L Thompson   @param[in]  rstr  CeedElemRestriction
701ea61e9acSJeremy L Thompson   @param[out] l_vec The address of the L-vector to be created, or NULL
702ea61e9acSJeremy L Thompson   @param[out] e_vec The address of the E-vector to be created, or NULL
703b11c1e72Sjeremylt 
704b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
705dfdf5a53Sjeremylt 
7067a982d89SJeremy L. Thompson   @ref User
707b11c1e72Sjeremylt **/
7082b730f8bSJeremy L Thompson int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, CeedVector *e_vec) {
709d2643443SJeremy L Thompson   CeedSize e_size, l_size;
710d1d35e2fSjeremylt   l_size = rstr->l_size;
711d1d35e2fSjeremylt   e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
7122b730f8bSJeremy L Thompson   if (l_vec) CeedCall(CeedVectorCreate(rstr->ceed, l_size, l_vec));
7132b730f8bSJeremy L Thompson   if (e_vec) CeedCall(CeedVectorCreate(rstr->ceed, e_size, e_vec));
714e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
715d7b241e6Sjeremylt }
716d7b241e6Sjeremylt 
717d7b241e6Sjeremylt /**
718d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
719d7b241e6Sjeremylt 
720ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
721ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
722ea61e9acSJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
723ea61e9acSJeremy L Thompson   @param[out] ru      Output vector (of shape [@a num_elem * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
724ea61e9acSJeremy L Thompson                         Ordering of the e-vector is decided by the backend.
725ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
726b11c1e72Sjeremylt 
727b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
728dfdf5a53Sjeremylt 
7297a982d89SJeremy L. Thompson   @ref User
730b11c1e72Sjeremylt **/
7312b730f8bSJeremy L Thompson int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
732d7b241e6Sjeremylt   CeedInt m, n;
733d7b241e6Sjeremylt 
734d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
735d1d35e2fSjeremylt     m = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
736d1d35e2fSjeremylt     n = rstr->l_size;
737d7b241e6Sjeremylt   } else {
738d1d35e2fSjeremylt     m = rstr->l_size;
739d1d35e2fSjeremylt     n = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
740d7b241e6Sjeremylt   }
7412b730f8bSJeremy L Thompson   if (n != u->length) {
742c042f62fSJeremy L Thompson     // LCOV_EXCL_START
743e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
7442b730f8bSJeremy L Thompson                      "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m,
7452b730f8bSJeremy L Thompson                      n);
746c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
74752b3e6a7SJed Brown   }
7482b730f8bSJeremy L Thompson   if (m != ru->length) {
7492b730f8bSJeremy L Thompson     // LCOV_EXCL_START
7502b730f8bSJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
7512b730f8bSJeremy L Thompson                      "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length,
7522b730f8bSJeremy L Thompson                      m, n);
7532b730f8bSJeremy L Thompson     // LCOV_EXCL_STOP
7542b730f8bSJeremy L Thompson   }
7552b730f8bSJeremy L Thompson   if (rstr->num_elem > 0) CeedCall(rstr->Apply(rstr, t_mode, u, ru, request));
756e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
757d7b241e6Sjeremylt }
758d7b241e6Sjeremylt 
759d7b241e6Sjeremylt /**
760d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
761be9261b7Sjeremylt 
762ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
763ea61e9acSJeremy L Thompson   @param[in]  block   Block number to restrict to/from, i.e. block=0 will handle elements [0 : blk_size] and block=3 will handle elements [3*blk_size
764ea61e9acSJeremy L Thompson : 4*blk_size]
765ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
766ea61e9acSJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
767ea61e9acSJeremy L Thompson   @param[out] ru      Output vector (of shape [@a blk_size * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
768ea61e9acSJeremy L Thompson                         Ordering of the e-vector is decided by the backend.
769ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
770be9261b7Sjeremylt 
771be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
772be9261b7Sjeremylt 
7737a982d89SJeremy L. Thompson   @ref Backend
774be9261b7Sjeremylt **/
7752b730f8bSJeremy L Thompson int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
7762b730f8bSJeremy L Thompson                                   CeedRequest *request) {
777be9261b7Sjeremylt   CeedInt m, n;
778be9261b7Sjeremylt 
779d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
780d1d35e2fSjeremylt     m = rstr->blk_size * rstr->elem_size * rstr->num_comp;
781d1d35e2fSjeremylt     n = rstr->l_size;
782be9261b7Sjeremylt   } else {
783d1d35e2fSjeremylt     m = rstr->l_size;
784d1d35e2fSjeremylt     n = rstr->blk_size * rstr->elem_size * rstr->num_comp;
785be9261b7Sjeremylt   }
7862b730f8bSJeremy L Thompson   if (n != u->length) {
787c042f62fSJeremy L Thompson     // LCOV_EXCL_START
788e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
7892b730f8bSJeremy L Thompson                      "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m,
7902b730f8bSJeremy L Thompson                      n);
791c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
7922b730f8bSJeremy L Thompson   }
7932b730f8bSJeremy L Thompson   if (m != ru->length) {
794c042f62fSJeremy L Thompson     // LCOV_EXCL_START
795e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
7962b730f8bSJeremy L Thompson                      "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length,
7972b730f8bSJeremy L Thompson                      m, n);
798c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
7992b730f8bSJeremy L Thompson   }
8002b730f8bSJeremy L Thompson   if (rstr->blk_size * block > rstr->num_elem) {
801c042f62fSJeremy L Thompson     // LCOV_EXCL_START
802e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
8032b730f8bSJeremy L Thompson                      "Cannot retrieve block %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", block,
8042b730f8bSJeremy L Thompson                      rstr->blk_size * block, rstr->num_elem);
805c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
8062b730f8bSJeremy L Thompson   }
8072b730f8bSJeremy L Thompson   CeedCall(rstr->ApplyBlock(rstr, block, t_mode, u, ru, request));
808e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
809be9261b7Sjeremylt }
810be9261b7Sjeremylt 
811be9261b7Sjeremylt /**
812b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedElemRestriction
813b7c9bbdaSJeremy L Thompson 
814ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
815b7c9bbdaSJeremy L Thompson   @param[out] ceed Variable to store Ceed
816b7c9bbdaSJeremy L Thompson 
817b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
818b7c9bbdaSJeremy L Thompson 
819b7c9bbdaSJeremy L Thompson   @ref Advanced
820b7c9bbdaSJeremy L Thompson **/
821b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
822b7c9bbdaSJeremy L Thompson   *ceed = rstr->ceed;
823b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
824b7c9bbdaSJeremy L Thompson }
825b7c9bbdaSJeremy L Thompson 
826b7c9bbdaSJeremy L Thompson /**
827d979a051Sjeremylt   @brief Get the L-vector component stride
828a681ae63Sjeremylt 
829ea61e9acSJeremy L Thompson   @param[in]  rstr        CeedElemRestriction
830d1d35e2fSjeremylt   @param[out] comp_stride Variable to store component stride
831a681ae63Sjeremylt 
832a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
833a681ae63Sjeremylt 
834b7c9bbdaSJeremy L Thompson   @ref Advanced
835a681ae63Sjeremylt **/
8362b730f8bSJeremy L Thompson int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, CeedInt *comp_stride) {
837d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
838e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
839a681ae63Sjeremylt }
840a681ae63Sjeremylt 
841a681ae63Sjeremylt /**
842a681ae63Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
843a681ae63Sjeremylt 
844ea61e9acSJeremy L Thompson   @param[in] rstr      CeedElemRestriction
845d1d35e2fSjeremylt   @param[out] num_elem Variable to store number of elements
846a681ae63Sjeremylt 
847a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
848a681ae63Sjeremylt 
849b7c9bbdaSJeremy L Thompson   @ref Advanced
850a681ae63Sjeremylt **/
8512b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, CeedInt *num_elem) {
852d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
853e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
854a681ae63Sjeremylt }
855a681ae63Sjeremylt 
856a681ae63Sjeremylt /**
857a681ae63Sjeremylt   @brief Get the size of elements in the CeedElemRestriction
858a681ae63Sjeremylt 
859ea61e9acSJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
860d1d35e2fSjeremylt   @param[out] elem_size Variable to store size of elements
861a681ae63Sjeremylt 
862a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
863a681ae63Sjeremylt 
864b7c9bbdaSJeremy L Thompson   @ref Advanced
865a681ae63Sjeremylt **/
8662b730f8bSJeremy L Thompson int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, CeedInt *elem_size) {
867d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
868e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
869a681ae63Sjeremylt }
870a681ae63Sjeremylt 
871a681ae63Sjeremylt /**
872d979a051Sjeremylt   @brief Get the size of the l-vector for a CeedElemRestriction
873a681ae63Sjeremylt 
874ea61e9acSJeremy L Thompson   @param[in]  rstr   CeedElemRestriction
875d1d35e2fSjeremylt   @param[out] l_size Variable to store number of nodes
876a681ae63Sjeremylt 
877a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
878a681ae63Sjeremylt 
879b7c9bbdaSJeremy L Thompson   @ref Advanced
880a681ae63Sjeremylt **/
8812b730f8bSJeremy L Thompson int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, CeedSize *l_size) {
882d1d35e2fSjeremylt   *l_size = rstr->l_size;
883e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
884a681ae63Sjeremylt }
885a681ae63Sjeremylt 
886a681ae63Sjeremylt /**
887ea61e9acSJeremy L Thompson   @brief Get the number of components in the elements of a CeedElemRestriction
888a681ae63Sjeremylt 
889ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction
890d1d35e2fSjeremylt   @param[out] num_comp Variable to store number of components
891a681ae63Sjeremylt 
892a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
893a681ae63Sjeremylt 
894b7c9bbdaSJeremy L Thompson   @ref Advanced
895a681ae63Sjeremylt **/
8962b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, CeedInt *num_comp) {
897d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
898e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
899a681ae63Sjeremylt }
900a681ae63Sjeremylt 
901a681ae63Sjeremylt /**
902a681ae63Sjeremylt   @brief Get the number of blocks in a CeedElemRestriction
903a681ae63Sjeremylt 
904ea61e9acSJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
905d1d35e2fSjeremylt   @param[out] num_block Variable to store number of blocks
906a681ae63Sjeremylt 
907a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
908a681ae63Sjeremylt 
909b7c9bbdaSJeremy L Thompson   @ref Advanced
910a681ae63Sjeremylt **/
9112b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, CeedInt *num_block) {
912d1d35e2fSjeremylt   *num_block = rstr->num_blk;
913e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
914a681ae63Sjeremylt }
915a681ae63Sjeremylt 
916a681ae63Sjeremylt /**
917a681ae63Sjeremylt   @brief Get the size of blocks in the CeedElemRestriction
918a681ae63Sjeremylt 
919ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction
920d1d35e2fSjeremylt   @param[out] blk_size Variable to store size of blocks
921a681ae63Sjeremylt 
922a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
923a681ae63Sjeremylt 
924b7c9bbdaSJeremy L Thompson   @ref Advanced
925a681ae63Sjeremylt **/
9262b730f8bSJeremy L Thompson int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, CeedInt *blk_size) {
927d1d35e2fSjeremylt   *blk_size = rstr->blk_size;
928e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
929a681ae63Sjeremylt }
930a681ae63Sjeremylt 
931a681ae63Sjeremylt /**
932d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
9331469ee4dSjeremylt 
934ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
935d1d35e2fSjeremylt   @param[out] mult Vector to store multiplicity (of size l_size)
9361469ee4dSjeremylt 
9371469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
9381469ee4dSjeremylt 
9397a982d89SJeremy L. Thompson   @ref User
9401469ee4dSjeremylt **/
9412b730f8bSJeremy L Thompson int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, CeedVector mult) {
942d1d35e2fSjeremylt   CeedVector e_vec;
9431469ee4dSjeremylt 
94425509ebbSRezgar Shakeri   // Create e_vec to hold intermediate computation in E^T (E 1)
9452b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionCreateVector(rstr, NULL, &e_vec));
9461469ee4dSjeremylt 
94725509ebbSRezgar Shakeri   // Compute e_vec = E * 1
9482b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 1.0));
9492b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, CEED_REQUEST_IMMEDIATE));
95025509ebbSRezgar Shakeri   // Compute multiplicity, mult = E^T * e_vec = E^T (E 1)
9512b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 0.0));
9522b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, CEED_REQUEST_IMMEDIATE));
9531469ee4dSjeremylt   // Cleanup
9542b730f8bSJeremy L Thompson   CeedCall(CeedVectorDestroy(&e_vec));
955e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
9561469ee4dSjeremylt }
9571469ee4dSjeremylt 
9581469ee4dSjeremylt /**
959f02ca4a2SJed Brown   @brief View a CeedElemRestriction
960f02ca4a2SJed Brown 
961f02ca4a2SJed Brown   @param[in] rstr   CeedElemRestriction to view
962f02ca4a2SJed Brown   @param[in] stream Stream to write; typically stdout/stderr or a file
963f02ca4a2SJed Brown 
964f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
965f02ca4a2SJed Brown 
9667a982d89SJeremy L. Thompson   @ref User
967f02ca4a2SJed Brown **/
968f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
9697509a596Sjeremylt   char stridesstr[500];
9702b730f8bSJeremy L Thompson   if (rstr->strides) {
9712b730f8bSJeremy L Thompson     sprintf(stridesstr, "[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "]", rstr->strides[0], rstr->strides[1], rstr->strides[2]);
9722b730f8bSJeremy L Thompson   } else {
973990fdeb6SJeremy L Thompson     sprintf(stridesstr, "%" CeedInt_FMT, rstr->comp_stride);
9742b730f8bSJeremy L Thompson   }
9757509a596Sjeremylt 
9762b730f8bSJeremy L Thompson   fprintf(stream, "%sCeedElemRestriction from (%td, %" CeedInt_FMT ") to %" CeedInt_FMT " elements with %" CeedInt_FMT " nodes each and %s %s\n",
9772b730f8bSJeremy L Thompson           rstr->blk_size > 1 ? "Blocked " : "", rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
978d979a051Sjeremylt           rstr->strides ? "strides" : "component stride", stridesstr);
979e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
980f02ca4a2SJed Brown }
981f02ca4a2SJed Brown 
982f02ca4a2SJed Brown /**
983b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
984b11c1e72Sjeremylt 
985ea61e9acSJeremy L Thompson   @param[in,out] rstr CeedElemRestriction to destroy
986b11c1e72Sjeremylt 
987b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
988dfdf5a53Sjeremylt 
9897a982d89SJeremy L. Thompson   @ref User
990b11c1e72Sjeremylt **/
9914ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
992ad6481ceSJeremy L Thompson   if (!*rstr || --(*rstr)->ref_count > 0) {
993ad6481ceSJeremy L Thompson     *rstr = NULL;
994ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
995ad6481ceSJeremy L Thompson   }
9962b730f8bSJeremy L Thompson   if ((*rstr)->num_readers) {
9978229195eSjeremylt     // LCOV_EXCL_START
9982b730f8bSJeremy L Thompson     return CeedError((*rstr)->ceed, CEED_ERROR_ACCESS, "Cannot destroy CeedElemRestriction, a process has read access to the offset data");
9998229195eSjeremylt     // LCOV_EXCL_STOP
1000d7b241e6Sjeremylt   }
10012b730f8bSJeremy L Thompson   if ((*rstr)->Destroy) CeedCall((*rstr)->Destroy(*rstr));
10022b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*rstr)->strides));
10032b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*rstr)->ceed));
10042b730f8bSJeremy L Thompson   CeedCall(CeedFree(rstr));
1005e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1006d7b241e6Sjeremylt }
1007d7b241e6Sjeremylt 
1008d7b241e6Sjeremylt /// @}
1009