xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-elemrestriction.c (revision b04eb3d9dcd03054fbe981a83f15e207a4bc97bc)
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>
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]) {
706574a04fSJeremy L Thompson   CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
712b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*strides)[i] = rstr->strides[i];
72e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
737a982d89SJeremy L. Thompson }
747a982d89SJeremy L. Thompson 
757a982d89SJeremy L. Thompson /**
76bd33150aSjeremylt   @brief Get read-only access to a CeedElemRestriction offsets array by memtype
77bd33150aSjeremylt 
78ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction to retrieve offsets
79ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the array.
80ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy (possibly cached).
81d1d35e2fSjeremylt   @param[out] offsets Array on memory type mem_type
82bd33150aSjeremylt 
83bd33150aSjeremylt   @return An error code: 0 - success, otherwise - failure
84bd33150aSjeremylt 
85bd33150aSjeremylt   @ref User
86bd33150aSjeremylt **/
872b730f8bSJeremy L Thompson int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) {
886574a04fSJeremy L Thompson   CeedCheck(rstr->GetOffsets, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetOffsets");
892b730f8bSJeremy L Thompson   CeedCall(rstr->GetOffsets(rstr, mem_type, offsets));
90d1d35e2fSjeremylt   rstr->num_readers++;
91e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
92430758c8SJeremy L Thompson }
93430758c8SJeremy L Thompson 
94430758c8SJeremy L Thompson /**
95430758c8SJeremy L Thompson   @brief Restore an offsets array obtained using CeedElemRestrictionGetOffsets()
96430758c8SJeremy L Thompson 
97ea61e9acSJeremy L Thompson   @param[in] rstr    CeedElemRestriction to restore
98ea61e9acSJeremy L Thompson   @param[in] offsets Array of offset data
99430758c8SJeremy L Thompson 
100430758c8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
101430758c8SJeremy L Thompson 
102430758c8SJeremy L Thompson   @ref User
103430758c8SJeremy L Thompson **/
1042b730f8bSJeremy L Thompson int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr, const CeedInt **offsets) {
105430758c8SJeremy L Thompson   *offsets = NULL;
106d1d35e2fSjeremylt   rstr->num_readers--;
107e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
108bd33150aSjeremylt }
109bd33150aSjeremylt 
110bd33150aSjeremylt /**
1113ac43b2cSJeremy L Thompson   @brief Get the strided status of a CeedElemRestriction
1123ac43b2cSJeremy L Thompson 
113ea61e9acSJeremy L Thompson   @param[in]  rstr        CeedElemRestriction
114d1d35e2fSjeremylt   @param[out] is_strided  Variable to store strided status, 1 if strided else 0
1153ac43b2cSJeremy L Thompson 
1163ac43b2cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1173ac43b2cSJeremy L Thompson 
1183ac43b2cSJeremy L Thompson   @ref Backend
1193ac43b2cSJeremy L Thompson **/
120d1d35e2fSjeremylt int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) {
121d1d35e2fSjeremylt   *is_strided = rstr->strides ? true : false;
122e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1233ac43b2cSJeremy L Thompson }
1243ac43b2cSJeremy L Thompson 
1253ac43b2cSJeremy L Thompson /**
126b435c5a6Srezgarshakeri   @brief Get oriented status of a CeedElemRestriction
127b435c5a6Srezgarshakeri 
128ea61e9acSJeremy L Thompson   @param[in]  rstr         CeedElemRestriction
129b435c5a6Srezgarshakeri   @param[out] is_oriented  Variable to store oriented status, 1 if oriented else 0
130b435c5a6Srezgarshakeri 
131b435c5a6Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
132b435c5a6Srezgarshakeri 
133b435c5a6Srezgarshakeri   @ref Backend
134b435c5a6Srezgarshakeri **/
135b435c5a6Srezgarshakeri int CeedElemRestrictionIsOriented(CeedElemRestriction rstr, bool *is_oriented) {
136b435c5a6Srezgarshakeri   *is_oriented = rstr->is_oriented;
137b435c5a6Srezgarshakeri   return CEED_ERROR_SUCCESS;
138b435c5a6Srezgarshakeri }
139b435c5a6Srezgarshakeri 
140b435c5a6Srezgarshakeri /**
141a681ae63Sjeremylt   @brief Get the backend stride status of a CeedElemRestriction
1427a982d89SJeremy L. Thompson 
143ea61e9acSJeremy L Thompson   @param[in]  rstr                 CeedElemRestriction
14496b902e2Sjeremylt   @param[out] has_backend_strides  Variable to store stride status
1457a982d89SJeremy L. Thompson 
1467a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1477a982d89SJeremy L. Thompson 
1487a982d89SJeremy L. Thompson   @ref Backend
1497a982d89SJeremy L. Thompson **/
1502b730f8bSJeremy L Thompson int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, bool *has_backend_strides) {
1516574a04fSJeremy L Thompson   CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
1522b730f8bSJeremy L Thompson   *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
153a681ae63Sjeremylt                           (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
154e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1557a982d89SJeremy L. Thompson }
1567a982d89SJeremy L. Thompson 
1577a982d89SJeremy L. Thompson /**
15849fd234cSJeremy L Thompson 
15949fd234cSJeremy L Thompson   @brief Get the E-vector layout of a CeedElemRestriction
16049fd234cSJeremy L Thompson 
161ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
162ea61e9acSJeremy L Thompson   @param[out] layout  Variable to store layout array, stored as [nodes, components, elements].
163ea61e9acSJeremy 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]
16449fd234cSJeremy L Thompson 
16549fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
16649fd234cSJeremy L Thompson 
16749fd234cSJeremy L Thompson   @ref Backend
16849fd234cSJeremy L Thompson **/
1692b730f8bSJeremy L Thompson int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, CeedInt (*layout)[3]) {
1706574a04fSJeremy L Thompson   CeedCheck(rstr->layout[0], rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no layout data");
1712b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*layout)[i] = rstr->layout[i];
172e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
17349fd234cSJeremy L Thompson }
17449fd234cSJeremy L Thompson 
17549fd234cSJeremy L Thompson /**
17649fd234cSJeremy L Thompson 
17749fd234cSJeremy L Thompson   @brief Set the E-vector layout of a CeedElemRestriction
17849fd234cSJeremy L Thompson 
179ea61e9acSJeremy L Thompson   @param[in] rstr   CeedElemRestriction
180ea61e9acSJeremy L Thompson   @param[in] layout Variable to containing layout array, stored as [nodes, components, elements].
181ea61e9acSJeremy 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]
18249fd234cSJeremy L Thompson 
18349fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
18449fd234cSJeremy L Thompson 
18549fd234cSJeremy L Thompson   @ref Backend
18649fd234cSJeremy L Thompson **/
1872b730f8bSJeremy L Thompson int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
1882b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) rstr->layout[i] = layout[i];
189e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
19049fd234cSJeremy L Thompson }
19149fd234cSJeremy L Thompson 
19249fd234cSJeremy L Thompson /**
1937a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedElemRestriction
1947a982d89SJeremy L. Thompson 
195ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
1967a982d89SJeremy L. Thompson   @param[out] data Variable to store data
1977a982d89SJeremy L. Thompson 
1987a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1997a982d89SJeremy L. Thompson 
2007a982d89SJeremy L. Thompson   @ref Backend
2017a982d89SJeremy L. Thompson **/
202777ff853SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) {
203777ff853SJeremy L Thompson   *(void **)data = rstr->data;
204e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2057a982d89SJeremy L. Thompson }
2067a982d89SJeremy L. Thompson 
2077a982d89SJeremy L. Thompson /**
2087a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedElemRestriction
2097a982d89SJeremy L. Thompson 
210ea61e9acSJeremy L Thompson   @param[in,out] rstr CeedElemRestriction
211ea61e9acSJeremy L Thompson   @param[in]     data Data to set
2127a982d89SJeremy L. Thompson 
2137a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2147a982d89SJeremy L. Thompson 
2157a982d89SJeremy L. Thompson   @ref Backend
2167a982d89SJeremy L. Thompson **/
217777ff853SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) {
218777ff853SJeremy L Thompson   rstr->data = data;
219e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2207a982d89SJeremy L. Thompson }
2217a982d89SJeremy L. Thompson 
22234359f16Sjeremylt /**
22334359f16Sjeremylt   @brief Increment the reference counter for a CeedElemRestriction
22434359f16Sjeremylt 
225ea61e9acSJeremy L Thompson   @param[in,out] rstr ElemRestriction to increment the reference counter
22634359f16Sjeremylt 
22734359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
22834359f16Sjeremylt 
22934359f16Sjeremylt   @ref Backend
23034359f16Sjeremylt **/
2319560d06aSjeremylt int CeedElemRestrictionReference(CeedElemRestriction rstr) {
23234359f16Sjeremylt   rstr->ref_count++;
23334359f16Sjeremylt   return CEED_ERROR_SUCCESS;
23434359f16Sjeremylt }
23534359f16Sjeremylt 
2366e15d496SJeremy L Thompson /**
2376e15d496SJeremy L Thompson   @brief Estimate number of FLOPs required to apply CeedElemRestriction in t_mode
2386e15d496SJeremy L Thompson 
239ea61e9acSJeremy L Thompson   @param[in]  rstr   ElemRestriction to estimate FLOPs for
240ea61e9acSJeremy L Thompson   @param[in]  t_mode Apply restriction or transpose
241ea61e9acSJeremy L Thompson   @param[out] flops  Address of variable to hold FLOPs estimate
2426e15d496SJeremy L Thompson 
2436e15d496SJeremy L Thompson   @ref Backend
2446e15d496SJeremy L Thompson **/
2452b730f8bSJeremy L Thompson int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedSize *flops) {
2466e15d496SJeremy L Thompson   bool    is_oriented;
2472b730f8bSJeremy L Thompson   CeedInt e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp, scale = 0;
2486e15d496SJeremy L Thompson 
2492b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionIsOriented(rstr, &is_oriented));
2506e15d496SJeremy L Thompson   switch (t_mode) {
2512b730f8bSJeremy L Thompson     case CEED_NOTRANSPOSE:
2522b730f8bSJeremy L Thompson       scale = is_oriented ? 1 : 0;
2532b730f8bSJeremy L Thompson       break;
2542b730f8bSJeremy L Thompson     case CEED_TRANSPOSE:
2552b730f8bSJeremy L Thompson       scale = is_oriented ? 2 : 1;
2562b730f8bSJeremy L Thompson       break;
2576e15d496SJeremy L Thompson   }
2586e15d496SJeremy L Thompson   *flops = e_size * scale;
2596e15d496SJeremy L Thompson 
2606e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2616e15d496SJeremy L Thompson }
2626e15d496SJeremy L Thompson 
2637a982d89SJeremy L. Thompson /// @}
2647a982d89SJeremy L. Thompson 
26515910d16Sjeremylt /// @cond DOXYGEN_SKIP
26615910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
26715910d16Sjeremylt /// @endcond
26815910d16Sjeremylt 
2697a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
2707a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
2717a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
2727a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
273d7b241e6Sjeremylt /// @{
274d7b241e6Sjeremylt 
2757a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
27645f1e315Sjeremylt const CeedInt CEED_STRIDES_BACKEND[3] = {0};
2777a982d89SJeremy L. Thompson 
2784cc79fe7SJed Brown /// Indicate that no CeedElemRestriction is provided by the user
2792b730f8bSJeremy L Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = &ceed_elemrestriction_none;
2807a982d89SJeremy L. Thompson 
281d7b241e6Sjeremylt /**
282b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
283d7b241e6Sjeremylt 
284ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
285ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array
286ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
287ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
288ea61e9acSJeremy L Thompson   @param[in]  comp_stride Stride between components for the same L-vector "node".
289ea61e9acSJeremy 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.
290ea61e9acSJeremy L Thompson   @param[in]  l_size      The size of the L-vector.
291ea61e9acSJeremy L Thompson                             This vector may be larger than the elements and fields given by this restriction.
292ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
293ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
294ea61e9acSJeremy L Thompson   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
295ea61e9acSJeremy L Thompson                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
296ea61e9acSJeremy L Thompson 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
297ea61e9acSJeremy L Thompson   @param[out] rstr    Address of the variable where the newly created CeedElemRestriction will be stored
298d7b241e6Sjeremylt 
299b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
300dfdf5a53Sjeremylt 
3017a982d89SJeremy L. Thompson   @ref User
302b11c1e72Sjeremylt **/
3032b730f8bSJeremy L Thompson int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
3042b730f8bSJeremy L Thompson                               CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
3055fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
3065fe0d4faSjeremylt     Ceed delegate;
3076574a04fSJeremy L Thompson 
3082b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
3096574a04fSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ElemRestrictionCreate");
3102b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
311e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
3125fe0d4faSjeremylt   }
3135fe0d4faSjeremylt 
3146574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
3156574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
3166574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
317e022e1f8SJeremy L Thompson 
3182b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
3194ce2993fSjeremylt   (*rstr)->ceed = ceed;
3202b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
321d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
322d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
323d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
324d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
325d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
326d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
327d1d35e2fSjeremylt   (*rstr)->num_blk     = num_elem;
328d1d35e2fSjeremylt   (*rstr)->blk_size    = 1;
3296402da51SJeremy L Thompson   (*rstr)->is_oriented = false;
3302b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, *rstr));
331e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
332d7b241e6Sjeremylt }
333d7b241e6Sjeremylt 
334d7b241e6Sjeremylt /**
335fc0567d9Srezgarshakeri   @brief Create a CeedElemRestriction with orientation sign
336fc0567d9Srezgarshakeri 
337ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
338ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array
339ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
340ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
341ea61e9acSJeremy L Thompson   @param[in]  comp_stride Stride between components for the same L-vector "node".
342ea61e9acSJeremy 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.
343ea61e9acSJeremy L Thompson   @param[in]  l_size      The size of the L-vector.
344ea61e9acSJeremy L Thompson                             This vector may be larger than the elements and fields given by this restriction.
345ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
346ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
347ea61e9acSJeremy L Thompson   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
348ea61e9acSJeremy L Thompson                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
349ea61e9acSJeremy L Thompson 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
350ea61e9acSJeremy 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.
351ea61e9acSJeremy L Thompson   @param[out] rstr       Address of the variable where the newly created CeedElemRestriction will be stored
352fc0567d9Srezgarshakeri 
353fc0567d9Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
354fc0567d9Srezgarshakeri 
355fc0567d9Srezgarshakeri   @ref User
356fc0567d9Srezgarshakeri **/
3572b730f8bSJeremy L Thompson int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
3582b730f8bSJeremy L Thompson                                       CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orient,
359fc0567d9Srezgarshakeri                                       CeedElemRestriction *rstr) {
360c7745053SRezgar Shakeri   if (!ceed->ElemRestrictionCreateOriented) {
361fc0567d9Srezgarshakeri     Ceed delegate;
3626574a04fSJeremy L Thompson 
3632b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
3646574a04fSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateOriented");
3652b730f8bSJeremy L Thompson     CeedCall(
3662b730f8bSJeremy L Thompson         CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, orient, rstr));
367fc0567d9Srezgarshakeri     return CEED_ERROR_SUCCESS;
368fc0567d9Srezgarshakeri   }
369fc0567d9Srezgarshakeri 
3706574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
3716574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
3726574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
373e022e1f8SJeremy L Thompson 
3742b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
375fc0567d9Srezgarshakeri   (*rstr)->ceed = ceed;
3762b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
377fc0567d9Srezgarshakeri   (*rstr)->ref_count   = 1;
378fc0567d9Srezgarshakeri   (*rstr)->num_elem    = num_elem;
379fc0567d9Srezgarshakeri   (*rstr)->elem_size   = elem_size;
380fc0567d9Srezgarshakeri   (*rstr)->num_comp    = num_comp;
381fc0567d9Srezgarshakeri   (*rstr)->comp_stride = comp_stride;
382fc0567d9Srezgarshakeri   (*rstr)->l_size      = l_size;
383fc0567d9Srezgarshakeri   (*rstr)->num_blk     = num_elem;
384fc0567d9Srezgarshakeri   (*rstr)->blk_size    = 1;
3856402da51SJeremy L Thompson   (*rstr)->is_oriented = true;
3862b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateOriented(mem_type, copy_mode, offsets, orient, *rstr));
387fc0567d9Srezgarshakeri   return CEED_ERROR_SUCCESS;
388fc0567d9Srezgarshakeri }
389fc0567d9Srezgarshakeri 
390fc0567d9Srezgarshakeri /**
3917509a596Sjeremylt   @brief Create a strided CeedElemRestriction
392d7b241e6Sjeremylt 
393ea61e9acSJeremy L Thompson   @param[in]  ceed      Ceed object where the CeedElemRestriction will be created
394ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
395ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
396ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation "node" (1 for scalar fields)
397ea61e9acSJeremy L Thompson   @param[in]  l_size    The size of the L-vector.
398ea61e9acSJeremy L Thompson                           This vector may be larger than the elements and fields given by this restriction.
399ea61e9acSJeremy L Thompson   @param[in]  strides   Array for strides between [nodes, components, elements].
400ea61e9acSJeremy 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].
401ea61e9acSJeremy L Thompson                           @a CEED_STRIDES_BACKEND may be used with vectors created by a Ceed backend.
402ea61e9acSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created CeedElemRestriction will be stored
403d7b241e6Sjeremylt 
404b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
405dfdf5a53Sjeremylt 
4067a982d89SJeremy L. Thompson   @ref User
407b11c1e72Sjeremylt **/
4082b730f8bSJeremy L Thompson int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedSize l_size, const CeedInt strides[3],
409f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
4105fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
4115fe0d4faSjeremylt     Ceed delegate;
412*b04eb3d9SSebastian Grimberg 
4132b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
4146402da51SJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ElemRestrictionCreateStrided");
4152b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, l_size, strides, rstr));
416e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
4175fe0d4faSjeremylt   }
4185fe0d4faSjeremylt 
4196574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
4206574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
421e022e1f8SJeremy L Thompson 
4222b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
4234ce2993fSjeremylt   (*rstr)->ceed = ceed;
4242b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
425d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
426d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
427d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
428d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
429d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
430d1d35e2fSjeremylt   (*rstr)->num_blk     = num_elem;
431d1d35e2fSjeremylt   (*rstr)->blk_size    = 1;
4326402da51SJeremy L Thompson   (*rstr)->is_oriented = false;
4332b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
4342b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
4352b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, *rstr));
436e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
437d7b241e6Sjeremylt }
438d7b241e6Sjeremylt 
439d7b241e6Sjeremylt /**
440b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
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 unknowns) per element
445ea61e9acSJeremy L Thompson   @param[in]  blk_size    Number of elements in a block
446ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
447ea61e9acSJeremy L Thompson   @param[in]  comp_stride Stride between components for the same L-vector "node".
448ea61e9acSJeremy 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.
449ea61e9acSJeremy L Thompson   @param[in]  l_size      The size of the L-vector.
450ea61e9acSJeremy L Thompson                             This vector may be larger than the elements and fields given by this restriction.
451ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
452ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
453ea61e9acSJeremy L Thompson   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
454ea61e9acSJeremy L Thompson                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
455ea61e9acSJeremy 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
456ea61e9acSJeremy L Thompson  the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
457ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
458d7b241e6Sjeremylt 
459b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
460dfdf5a53Sjeremylt 
4617a982d89SJeremy L. Thompson   @ref Backend
462b11c1e72Sjeremylt  **/
4632b730f8bSJeremy L Thompson int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedInt comp_stride,
4642b730f8bSJeremy L Thompson                                      CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets,
4654ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
466d1d35e2fSjeremylt   CeedInt *blk_offsets;
467d1d35e2fSjeremylt   CeedInt  num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
468d7b241e6Sjeremylt 
4695fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
4705fe0d4faSjeremylt     Ceed delegate;
4716574a04fSJeremy L Thompson 
4722b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
4736402da51SJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
4742b730f8bSJeremy L Thompson     CeedCall(
4752b730f8bSJeremy L Thompson         CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, blk_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
476e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
4775fe0d4faSjeremylt   }
478d7b241e6Sjeremylt 
4796574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
4806574a04fSJeremy L Thompson   CeedCheck(blk_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
4816574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
4826574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
483e022e1f8SJeremy L Thompson 
4842b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
485d7b241e6Sjeremylt 
4862b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(num_blk * blk_size * elem_size, &blk_offsets));
4872b730f8bSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size, elem_size));
488d7b241e6Sjeremylt 
4894ce2993fSjeremylt   (*rstr)->ceed = ceed;
4902b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
491d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
492d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
493d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
494d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
495d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
496d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
497d1d35e2fSjeremylt   (*rstr)->num_blk     = num_blk;
498d1d35e2fSjeremylt   (*rstr)->blk_size    = blk_size;
4996402da51SJeremy L Thompson   (*rstr)->is_oriented = false;
5002b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)blk_offsets, *rstr));
501d1d35e2fSjeremylt   if (copy_mode == CEED_OWN_POINTER) {
5022b730f8bSJeremy L Thompson     CeedCall(CeedFree(&offsets));
5031d102b48SJeremy L Thompson   }
504e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
505d7b241e6Sjeremylt }
506d7b241e6Sjeremylt 
507b11c1e72Sjeremylt /**
5087509a596Sjeremylt   @brief Create a blocked strided CeedElemRestriction
5097509a596Sjeremylt 
510ea61e9acSJeremy L Thompson   @param[in]  ceed      Ceed object where the CeedElemRestriction will be created
511ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
512ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
513ea61e9acSJeremy L Thompson   @param[in]  blk_size  Number of elements in a block
514ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation node (1 for scalar fields)
515ea61e9acSJeremy L Thompson   @param[in]  l_size    The size of the L-vector.
516ea61e9acSJeremy L Thompson                           This vector may be larger than the elements and fields given by this restriction.
517ea61e9acSJeremy L Thompson   @param[in]  strides   Array for strides between [nodes, components, elements].
518ea61e9acSJeremy 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].
519ea61e9acSJeremy L Thompson                           @a CEED_STRIDES_BACKEND may be used with vectors created by a Ceed backend.
520ea61e9acSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created CeedElemRestriction will be stored
5217509a596Sjeremylt 
5227509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
5237509a596Sjeremylt 
5247a982d89SJeremy L. Thompson   @ref User
5257509a596Sjeremylt **/
5262b730f8bSJeremy L Thompson int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedSize l_size,
5278621c6c6SJeremy L Thompson                                             const CeedInt strides[3], CeedElemRestriction *rstr) {
528d1d35e2fSjeremylt   CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
5297509a596Sjeremylt 
5307509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
5317509a596Sjeremylt     Ceed delegate;
5326574a04fSJeremy L Thompson 
5332b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
5346402da51SJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlockedStrided");
5352b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, blk_size, num_comp, l_size, strides, rstr));
536e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
5377509a596Sjeremylt   }
5387509a596Sjeremylt 
5396574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
5406574a04fSJeremy L Thompson   CeedCheck(blk_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
5416574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
542e022e1f8SJeremy L Thompson 
5432b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
5447509a596Sjeremylt 
5457509a596Sjeremylt   (*rstr)->ceed = ceed;
5462b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
547d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
548d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
549d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
550d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
551d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
552d1d35e2fSjeremylt   (*rstr)->num_blk     = num_blk;
553d1d35e2fSjeremylt   (*rstr)->blk_size    = blk_size;
5546402da51SJeremy L Thompson   (*rstr)->is_oriented = false;
5552b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
5562b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
5572b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, *rstr));
558e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5597509a596Sjeremylt }
5607509a596Sjeremylt 
5617509a596Sjeremylt /**
562ea61e9acSJeremy L Thompson   @brief Copy the pointer to a CeedElemRestriction.
5639fd66db6SSebastian Grimberg 
564ea61e9acSJeremy L Thompson   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
5659560d06aSjeremylt 
5669fd66db6SSebastian 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.
5679fd66db6SSebastian Grimberg         This CeedElemRestriction will be destroyed if `rstr_copy` is the only reference to this CeedElemRestriction.
568ea61e9acSJeremy L Thompson 
569ea61e9acSJeremy L Thompson   @param[in]     rstr      CeedElemRestriction to copy reference to
570ea61e9acSJeremy L Thompson   @param[in,out] rstr_copy Variable to store copied reference
5719560d06aSjeremylt 
5729560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
5739560d06aSjeremylt 
5749560d06aSjeremylt   @ref User
5759560d06aSjeremylt **/
5762b730f8bSJeremy L Thompson int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_copy) {
577393ac2cdSJeremy L Thompson   if (rstr != CEED_ELEMRESTRICTION_NONE) CeedCall(CeedElemRestrictionReference(rstr));
5782b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionDestroy(rstr_copy));
5799560d06aSjeremylt   *rstr_copy = rstr;
5809560d06aSjeremylt   return CEED_ERROR_SUCCESS;
5819560d06aSjeremylt }
5829560d06aSjeremylt 
5839560d06aSjeremylt /**
584b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
585b11c1e72Sjeremylt 
586ea61e9acSJeremy L Thompson   @param[in]  rstr  CeedElemRestriction
587ea61e9acSJeremy L Thompson   @param[out] l_vec The address of the L-vector to be created, or NULL
588ea61e9acSJeremy L Thompson   @param[out] e_vec The address of the E-vector to be created, or NULL
589b11c1e72Sjeremylt 
590b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
591dfdf5a53Sjeremylt 
5927a982d89SJeremy L. Thompson   @ref User
593b11c1e72Sjeremylt **/
5942b730f8bSJeremy L Thompson int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, CeedVector *e_vec) {
595d2643443SJeremy L Thompson   CeedSize e_size, l_size;
596d1d35e2fSjeremylt   l_size = rstr->l_size;
597d1d35e2fSjeremylt   e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
5982b730f8bSJeremy L Thompson   if (l_vec) CeedCall(CeedVectorCreate(rstr->ceed, l_size, l_vec));
5992b730f8bSJeremy L Thompson   if (e_vec) CeedCall(CeedVectorCreate(rstr->ceed, e_size, e_vec));
600e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
601d7b241e6Sjeremylt }
602d7b241e6Sjeremylt 
603d7b241e6Sjeremylt /**
604d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
605d7b241e6Sjeremylt 
606ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
607ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
608ea61e9acSJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
609ea61e9acSJeremy L Thompson   @param[out] ru      Output vector (of shape [@a num_elem * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
610ea61e9acSJeremy L Thompson                         Ordering of the e-vector is decided by the backend.
611ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
612b11c1e72Sjeremylt 
613b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
614dfdf5a53Sjeremylt 
6157a982d89SJeremy L. Thompson   @ref User
616b11c1e72Sjeremylt **/
6172b730f8bSJeremy L Thompson int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
618d7b241e6Sjeremylt   CeedInt m, n;
619d7b241e6Sjeremylt 
620d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
621d1d35e2fSjeremylt     m = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
622d1d35e2fSjeremylt     n = rstr->l_size;
623d7b241e6Sjeremylt   } else {
624d1d35e2fSjeremylt     m = rstr->l_size;
625d1d35e2fSjeremylt     n = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
626d7b241e6Sjeremylt   }
6276574a04fSJeremy L Thompson   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
6286574a04fSJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
6296574a04fSJeremy L Thompson   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
6306574a04fSJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
6312b730f8bSJeremy L Thompson   if (rstr->num_elem > 0) CeedCall(rstr->Apply(rstr, t_mode, u, ru, request));
632e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
633d7b241e6Sjeremylt }
634d7b241e6Sjeremylt 
635d7b241e6Sjeremylt /**
636f30b1135SSebastian Grimberg   @brief Restrict an L-vector to an E-vector or apply its transpose ignoring any
637f30b1135SSebastian Grimberg          provided orientations
638f30b1135SSebastian Grimberg 
639f30b1135SSebastian Grimberg   @param[in]  rstr    CeedElemRestriction
640f30b1135SSebastian Grimberg   @param[in]  t_mode  Apply restriction or transpose
641f30b1135SSebastian Grimberg   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
642f30b1135SSebastian Grimberg   @param[out] ru      Output vector (of shape [@a num_elem * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
643f30b1135SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
644f30b1135SSebastian Grimberg   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
645f30b1135SSebastian Grimberg 
646f30b1135SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
647f30b1135SSebastian Grimberg 
648f30b1135SSebastian Grimberg   @ref User
649f30b1135SSebastian Grimberg **/
650f30b1135SSebastian Grimberg int CeedElemRestrictionApplyUnsigned(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
651f30b1135SSebastian Grimberg   CeedInt m, n;
652f30b1135SSebastian Grimberg 
653*b04eb3d9SSebastian Grimberg   CeedCheck(rstr->ApplyUnsigned, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ElemRestrictionApplyUnsigned");
654b17517eeSSebastian Grimberg 
655f30b1135SSebastian Grimberg   if (t_mode == CEED_NOTRANSPOSE) {
656f30b1135SSebastian Grimberg     m = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
657f30b1135SSebastian Grimberg     n = rstr->l_size;
658f30b1135SSebastian Grimberg   } else {
659f30b1135SSebastian Grimberg     m = rstr->l_size;
660f30b1135SSebastian Grimberg     n = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
661f30b1135SSebastian Grimberg   }
662c7be5f81SSebastian Grimberg   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
663c7be5f81SSebastian Grimberg             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
664c7be5f81SSebastian Grimberg   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
665c7be5f81SSebastian Grimberg             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
666b17517eeSSebastian Grimberg   if (rstr->num_elem > 0) CeedCall(rstr->ApplyUnsigned(rstr, t_mode, u, ru, request));
667f30b1135SSebastian Grimberg   return CEED_ERROR_SUCCESS;
668f30b1135SSebastian Grimberg }
669f30b1135SSebastian Grimberg 
670f30b1135SSebastian Grimberg /**
671d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
672be9261b7Sjeremylt 
673ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
674ea61e9acSJeremy 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
675ea61e9acSJeremy L Thompson : 4*blk_size]
676ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
677ea61e9acSJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
678ea61e9acSJeremy L Thompson   @param[out] ru      Output vector (of shape [@a blk_size * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
679ea61e9acSJeremy L Thompson                         Ordering of the e-vector is decided by the backend.
680ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
681be9261b7Sjeremylt 
682be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
683be9261b7Sjeremylt 
6847a982d89SJeremy L. Thompson   @ref Backend
685be9261b7Sjeremylt **/
6862b730f8bSJeremy L Thompson int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
6872b730f8bSJeremy L Thompson                                   CeedRequest *request) {
688be9261b7Sjeremylt   CeedInt m, n;
689be9261b7Sjeremylt 
6906402da51SJeremy L Thompson   CeedCheck(rstr->ApplyBlock, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionApplyBlock");
6916402da51SJeremy L Thompson 
692d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
693d1d35e2fSjeremylt     m = rstr->blk_size * rstr->elem_size * rstr->num_comp;
694d1d35e2fSjeremylt     n = rstr->l_size;
695be9261b7Sjeremylt   } else {
696d1d35e2fSjeremylt     m = rstr->l_size;
697d1d35e2fSjeremylt     n = rstr->blk_size * rstr->elem_size * rstr->num_comp;
698be9261b7Sjeremylt   }
6996574a04fSJeremy L Thompson   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
7006574a04fSJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
7016574a04fSJeremy L Thompson   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
7026574a04fSJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
7036574a04fSJeremy L Thompson   CeedCheck(rstr->blk_size * block <= rstr->num_elem, rstr->ceed, CEED_ERROR_DIMENSION,
7046574a04fSJeremy L Thompson             "Cannot retrieve block %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", block, rstr->blk_size * block,
7056574a04fSJeremy L Thompson             rstr->num_elem);
7062b730f8bSJeremy L Thompson   CeedCall(rstr->ApplyBlock(rstr, block, t_mode, u, ru, request));
707e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
708be9261b7Sjeremylt }
709be9261b7Sjeremylt 
710be9261b7Sjeremylt /**
711b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedElemRestriction
712b7c9bbdaSJeremy L Thompson 
713ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
714b7c9bbdaSJeremy L Thompson   @param[out] ceed Variable to store Ceed
715b7c9bbdaSJeremy L Thompson 
716b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
717b7c9bbdaSJeremy L Thompson 
718b7c9bbdaSJeremy L Thompson   @ref Advanced
719b7c9bbdaSJeremy L Thompson **/
720b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
721b7c9bbdaSJeremy L Thompson   *ceed = rstr->ceed;
722b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
723b7c9bbdaSJeremy L Thompson }
724b7c9bbdaSJeremy L Thompson 
725b7c9bbdaSJeremy L Thompson /**
726d979a051Sjeremylt   @brief Get the L-vector component stride
727a681ae63Sjeremylt 
728ea61e9acSJeremy L Thompson   @param[in]  rstr        CeedElemRestriction
729d1d35e2fSjeremylt   @param[out] comp_stride Variable to store component stride
730a681ae63Sjeremylt 
731a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
732a681ae63Sjeremylt 
733b7c9bbdaSJeremy L Thompson   @ref Advanced
734a681ae63Sjeremylt **/
7352b730f8bSJeremy L Thompson int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, CeedInt *comp_stride) {
736d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
737e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
738a681ae63Sjeremylt }
739a681ae63Sjeremylt 
740a681ae63Sjeremylt /**
741a681ae63Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
742a681ae63Sjeremylt 
743ea61e9acSJeremy L Thompson   @param[in] rstr      CeedElemRestriction
744d1d35e2fSjeremylt   @param[out] num_elem Variable to store number of elements
745a681ae63Sjeremylt 
746a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
747a681ae63Sjeremylt 
748b7c9bbdaSJeremy L Thompson   @ref Advanced
749a681ae63Sjeremylt **/
7502b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, CeedInt *num_elem) {
751d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
752e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
753a681ae63Sjeremylt }
754a681ae63Sjeremylt 
755a681ae63Sjeremylt /**
756a681ae63Sjeremylt   @brief Get the size of elements in the CeedElemRestriction
757a681ae63Sjeremylt 
758ea61e9acSJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
759d1d35e2fSjeremylt   @param[out] elem_size Variable to store size of elements
760a681ae63Sjeremylt 
761a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
762a681ae63Sjeremylt 
763b7c9bbdaSJeremy L Thompson   @ref Advanced
764a681ae63Sjeremylt **/
7652b730f8bSJeremy L Thompson int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, CeedInt *elem_size) {
766d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
767e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
768a681ae63Sjeremylt }
769a681ae63Sjeremylt 
770a681ae63Sjeremylt /**
771d979a051Sjeremylt   @brief Get the size of the l-vector for a CeedElemRestriction
772a681ae63Sjeremylt 
773ea61e9acSJeremy L Thompson   @param[in]  rstr   CeedElemRestriction
774d1d35e2fSjeremylt   @param[out] l_size Variable to store number of nodes
775a681ae63Sjeremylt 
776a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
777a681ae63Sjeremylt 
778b7c9bbdaSJeremy L Thompson   @ref Advanced
779a681ae63Sjeremylt **/
7802b730f8bSJeremy L Thompson int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, CeedSize *l_size) {
781d1d35e2fSjeremylt   *l_size = rstr->l_size;
782e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
783a681ae63Sjeremylt }
784a681ae63Sjeremylt 
785a681ae63Sjeremylt /**
786ea61e9acSJeremy L Thompson   @brief Get the number of components in the elements of a CeedElemRestriction
787a681ae63Sjeremylt 
788ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction
789d1d35e2fSjeremylt   @param[out] num_comp Variable to store number of components
790a681ae63Sjeremylt 
791a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
792a681ae63Sjeremylt 
793b7c9bbdaSJeremy L Thompson   @ref Advanced
794a681ae63Sjeremylt **/
7952b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, CeedInt *num_comp) {
796d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
797e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
798a681ae63Sjeremylt }
799a681ae63Sjeremylt 
800a681ae63Sjeremylt /**
801a681ae63Sjeremylt   @brief Get the number of blocks in a CeedElemRestriction
802a681ae63Sjeremylt 
803ea61e9acSJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
804d1d35e2fSjeremylt   @param[out] num_block Variable to store number of blocks
805a681ae63Sjeremylt 
806a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
807a681ae63Sjeremylt 
808b7c9bbdaSJeremy L Thompson   @ref Advanced
809a681ae63Sjeremylt **/
8102b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, CeedInt *num_block) {
811d1d35e2fSjeremylt   *num_block = rstr->num_blk;
812e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
813a681ae63Sjeremylt }
814a681ae63Sjeremylt 
815a681ae63Sjeremylt /**
816a681ae63Sjeremylt   @brief Get the size of blocks in the CeedElemRestriction
817a681ae63Sjeremylt 
818ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction
819d1d35e2fSjeremylt   @param[out] blk_size Variable to store size of blocks
820a681ae63Sjeremylt 
821a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
822a681ae63Sjeremylt 
823b7c9bbdaSJeremy L Thompson   @ref Advanced
824a681ae63Sjeremylt **/
8252b730f8bSJeremy L Thompson int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, CeedInt *blk_size) {
826d1d35e2fSjeremylt   *blk_size = rstr->blk_size;
827e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
828a681ae63Sjeremylt }
829a681ae63Sjeremylt 
830a681ae63Sjeremylt /**
831d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
8321469ee4dSjeremylt 
833ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
834d1d35e2fSjeremylt   @param[out] mult Vector to store multiplicity (of size l_size)
8351469ee4dSjeremylt 
8361469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
8371469ee4dSjeremylt 
8387a982d89SJeremy L. Thompson   @ref User
8391469ee4dSjeremylt **/
8402b730f8bSJeremy L Thompson int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, CeedVector mult) {
841d1d35e2fSjeremylt   CeedVector e_vec;
8421469ee4dSjeremylt 
84325509ebbSRezgar Shakeri   // Create e_vec to hold intermediate computation in E^T (E 1)
8442b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionCreateVector(rstr, NULL, &e_vec));
8451469ee4dSjeremylt 
84625509ebbSRezgar Shakeri   // Compute e_vec = E * 1
8472b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 1.0));
8482b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, CEED_REQUEST_IMMEDIATE));
84925509ebbSRezgar Shakeri   // Compute multiplicity, mult = E^T * e_vec = E^T (E 1)
8502b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 0.0));
8512b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, CEED_REQUEST_IMMEDIATE));
8521469ee4dSjeremylt   // Cleanup
8532b730f8bSJeremy L Thompson   CeedCall(CeedVectorDestroy(&e_vec));
854e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
8551469ee4dSjeremylt }
8561469ee4dSjeremylt 
8571469ee4dSjeremylt /**
858f02ca4a2SJed Brown   @brief View a CeedElemRestriction
859f02ca4a2SJed Brown 
860f02ca4a2SJed Brown   @param[in] rstr   CeedElemRestriction to view
861f02ca4a2SJed Brown   @param[in] stream Stream to write; typically stdout/stderr or a file
862f02ca4a2SJed Brown 
863f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
864f02ca4a2SJed Brown 
8657a982d89SJeremy L. Thompson   @ref User
866f02ca4a2SJed Brown **/
867f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
8687509a596Sjeremylt   char stridesstr[500];
8692b730f8bSJeremy L Thompson   if (rstr->strides) {
8702b730f8bSJeremy L Thompson     sprintf(stridesstr, "[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "]", rstr->strides[0], rstr->strides[1], rstr->strides[2]);
8712b730f8bSJeremy L Thompson   } else {
872990fdeb6SJeremy L Thompson     sprintf(stridesstr, "%" CeedInt_FMT, rstr->comp_stride);
8732b730f8bSJeremy L Thompson   }
8747509a596Sjeremylt 
8752b730f8bSJeremy L Thompson   fprintf(stream, "%sCeedElemRestriction from (%td, %" CeedInt_FMT ") to %" CeedInt_FMT " elements with %" CeedInt_FMT " nodes each and %s %s\n",
8762b730f8bSJeremy L Thompson           rstr->blk_size > 1 ? "Blocked " : "", rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
877d979a051Sjeremylt           rstr->strides ? "strides" : "component stride", stridesstr);
878e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
879f02ca4a2SJed Brown }
880f02ca4a2SJed Brown 
881f02ca4a2SJed Brown /**
882b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
883b11c1e72Sjeremylt 
884ea61e9acSJeremy L Thompson   @param[in,out] rstr CeedElemRestriction to destroy
885b11c1e72Sjeremylt 
886b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
887dfdf5a53Sjeremylt 
8887a982d89SJeremy L. Thompson   @ref User
889b11c1e72Sjeremylt **/
8904ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
891393ac2cdSJeremy L Thompson   if (!*rstr || *rstr == CEED_ELEMRESTRICTION_NONE || --(*rstr)->ref_count > 0) {
892ad6481ceSJeremy L Thompson     *rstr = NULL;
893ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
894ad6481ceSJeremy L Thompson   }
8956574a04fSJeremy L Thompson   CeedCheck((*rstr)->num_readers == 0, (*rstr)->ceed, CEED_ERROR_ACCESS,
8966574a04fSJeremy L Thompson             "Cannot destroy CeedElemRestriction, a process has read access to the offset data");
8972b730f8bSJeremy L Thompson   if ((*rstr)->Destroy) CeedCall((*rstr)->Destroy(*rstr));
8982b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*rstr)->strides));
8992b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*rstr)->ceed));
9002b730f8bSJeremy L Thompson   CeedCall(CeedFree(rstr));
901e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
902d7b241e6Sjeremylt }
903d7b241e6Sjeremylt 
904d7b241e6Sjeremylt /// @}
905