xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-elemrestriction.c (revision c17ec2be5925899f8dbadb36e34e9a5bd9f00203)
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>
13*c17ec2beSJeremy L Thompson #include <string.h>
14d7b241e6Sjeremylt 
157a982d89SJeremy L. Thompson /// @file
167a982d89SJeremy L. Thompson /// Implementation of CeedElemRestriction interfaces
177a982d89SJeremy L. Thompson 
187a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
197a982d89SJeremy L. Thompson /// CeedElemRestriction Library Internal Functions
207a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
217a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionDeveloper
227a982d89SJeremy L. Thompson /// @{
237a982d89SJeremy L. Thompson 
247a982d89SJeremy L. Thompson /**
25d979a051Sjeremylt   @brief Permute and pad offsets for a blocked restriction
267a982d89SJeremy L. Thompson 
27ea61e9acSJeremy L Thompson   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
28ea61e9acSJeremy L Thompson                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
29ea61e9acSJeremy L Thompson 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
30ea61e9acSJeremy L Thompson   @param[out] blk_offsets Array of permuted and padded offsets of shape [@a num_blk, @a elem_size, @a blk_size].
31ea61e9acSJeremy L Thompson   @param[in]  num_blk     Number of blocks
32ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements
33ea61e9acSJeremy L Thompson   @param[in]  blk_size    Number of elements in a block
34ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size of each element
357a982d89SJeremy L. Thompson 
367a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
377a982d89SJeremy L. Thompson 
387a982d89SJeremy L. Thompson   @ref Utility
397a982d89SJeremy L. Thompson **/
402b730f8bSJeremy L Thompson int CeedPermutePadOffsets(const CeedInt *offsets, CeedInt *blk_offsets, CeedInt num_blk, CeedInt num_elem, CeedInt blk_size, CeedInt elem_size) {
412b730f8bSJeremy L Thompson   for (CeedInt e = 0; e < num_blk * blk_size; e += blk_size) {
422b730f8bSJeremy L Thompson     for (CeedInt j = 0; j < blk_size; j++) {
432b730f8bSJeremy L Thompson       for (CeedInt k = 0; k < elem_size; k++) {
442b730f8bSJeremy L Thompson         blk_offsets[e * elem_size + k * blk_size + j] = offsets[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
452b730f8bSJeremy L Thompson       }
462b730f8bSJeremy L Thompson     }
472b730f8bSJeremy L Thompson   }
48e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
497a982d89SJeremy L. Thompson }
507a982d89SJeremy L. Thompson 
517a982d89SJeremy L. Thompson /// @}
527a982d89SJeremy L. Thompson 
537a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
547a982d89SJeremy L. Thompson /// CeedElemRestriction Backend API
557a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
567a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionBackend
577a982d89SJeremy L. Thompson /// @{
587a982d89SJeremy L. Thompson 
597a982d89SJeremy L. Thompson /**
60a681ae63Sjeremylt 
61a681ae63Sjeremylt   @brief Get the strides of a strided CeedElemRestriction
627a982d89SJeremy L. Thompson 
63ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
64a681ae63Sjeremylt   @param[out] strides Variable to store strides array
657a982d89SJeremy L. Thompson 
667a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
677a982d89SJeremy L. Thompson 
687a982d89SJeremy L. Thompson   @ref Backend
697a982d89SJeremy L. Thompson **/
702b730f8bSJeremy L Thompson int CeedElemRestrictionGetStrides(CeedElemRestriction rstr, CeedInt (*strides)[3]) {
716574a04fSJeremy L Thompson   CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
722b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*strides)[i] = rstr->strides[i];
73e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
747a982d89SJeremy L. Thompson }
757a982d89SJeremy L. Thompson 
767a982d89SJeremy L. Thompson /**
77bd33150aSjeremylt   @brief Get read-only access to a CeedElemRestriction offsets array by memtype
78bd33150aSjeremylt 
79ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction to retrieve offsets
80ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the array.
81ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy (possibly cached).
82d1d35e2fSjeremylt   @param[out] offsets Array on memory type mem_type
83bd33150aSjeremylt 
84bd33150aSjeremylt   @return An error code: 0 - success, otherwise - failure
85bd33150aSjeremylt 
86bd33150aSjeremylt   @ref User
87bd33150aSjeremylt **/
882b730f8bSJeremy L Thompson int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) {
89*c17ec2beSJeremy L Thompson   if (rstr->rstr_signed) {
90*c17ec2beSJeremy L Thompson     CeedCall(CeedElemRestrictionGetOffsets(rstr->rstr_signed, mem_type, offsets));
91*c17ec2beSJeremy L Thompson   } else {
926574a04fSJeremy L Thompson     CeedCheck(rstr->GetOffsets, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetOffsets");
932b730f8bSJeremy L Thompson     CeedCall(rstr->GetOffsets(rstr, mem_type, offsets));
94d1d35e2fSjeremylt     rstr->num_readers++;
95*c17ec2beSJeremy L Thompson   }
96e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
97430758c8SJeremy L Thompson }
98430758c8SJeremy L Thompson 
99430758c8SJeremy L Thompson /**
100430758c8SJeremy L Thompson   @brief Restore an offsets array obtained using CeedElemRestrictionGetOffsets()
101430758c8SJeremy L Thompson 
102ea61e9acSJeremy L Thompson   @param[in] rstr    CeedElemRestriction to restore
103ea61e9acSJeremy L Thompson   @param[in] offsets Array of offset data
104430758c8SJeremy L Thompson 
105430758c8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
106430758c8SJeremy L Thompson 
107430758c8SJeremy L Thompson   @ref User
108430758c8SJeremy L Thompson **/
1092b730f8bSJeremy L Thompson int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr, const CeedInt **offsets) {
110*c17ec2beSJeremy L Thompson   if (rstr->rstr_signed) {
111*c17ec2beSJeremy L Thompson     CeedCall(CeedElemRestrictionRestoreOffsets(rstr->rstr_signed, offsets));
112*c17ec2beSJeremy L Thompson   } else {
113430758c8SJeremy L Thompson     *offsets = NULL;
114d1d35e2fSjeremylt     rstr->num_readers--;
115*c17ec2beSJeremy L Thompson   }
116e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
117bd33150aSjeremylt }
118bd33150aSjeremylt 
119bd33150aSjeremylt /**
1203ac43b2cSJeremy L Thompson   @brief Get the strided status of a CeedElemRestriction
1213ac43b2cSJeremy L Thompson 
122ea61e9acSJeremy L Thompson   @param[in]  rstr        CeedElemRestriction
123d1d35e2fSjeremylt   @param[out] is_strided  Variable to store strided status, 1 if strided else 0
1243ac43b2cSJeremy L Thompson 
1253ac43b2cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1263ac43b2cSJeremy L Thompson 
1273ac43b2cSJeremy L Thompson   @ref Backend
1283ac43b2cSJeremy L Thompson **/
129d1d35e2fSjeremylt int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) {
130d1d35e2fSjeremylt   *is_strided = rstr->strides ? true : false;
131e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1323ac43b2cSJeremy L Thompson }
1333ac43b2cSJeremy L Thompson 
1343ac43b2cSJeremy L Thompson /**
135b435c5a6Srezgarshakeri   @brief Get oriented status of a CeedElemRestriction
136b435c5a6Srezgarshakeri 
137ea61e9acSJeremy L Thompson   @param[in]  rstr         CeedElemRestriction
138b435c5a6Srezgarshakeri   @param[out] is_oriented  Variable to store oriented status, 1 if oriented else 0
139b435c5a6Srezgarshakeri 
140b435c5a6Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
141b435c5a6Srezgarshakeri 
142b435c5a6Srezgarshakeri   @ref Backend
143b435c5a6Srezgarshakeri **/
144b435c5a6Srezgarshakeri int CeedElemRestrictionIsOriented(CeedElemRestriction rstr, bool *is_oriented) {
145b435c5a6Srezgarshakeri   *is_oriented = rstr->is_oriented;
146b435c5a6Srezgarshakeri   return CEED_ERROR_SUCCESS;
147b435c5a6Srezgarshakeri }
148b435c5a6Srezgarshakeri 
149b435c5a6Srezgarshakeri /**
150a681ae63Sjeremylt   @brief Get the backend stride status of a CeedElemRestriction
1517a982d89SJeremy L. Thompson 
152ea61e9acSJeremy L Thompson   @param[in]  rstr                 CeedElemRestriction
15396b902e2Sjeremylt   @param[out] has_backend_strides  Variable to store stride status
1547a982d89SJeremy L. Thompson 
1557a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1567a982d89SJeremy L. Thompson 
1577a982d89SJeremy L. Thompson   @ref Backend
1587a982d89SJeremy L. Thompson **/
1592b730f8bSJeremy L Thompson int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, bool *has_backend_strides) {
1606574a04fSJeremy L Thompson   CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
1612b730f8bSJeremy L Thompson   *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
162a681ae63Sjeremylt                           (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
163e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1647a982d89SJeremy L. Thompson }
1657a982d89SJeremy L. Thompson 
1667a982d89SJeremy L. Thompson /**
16749fd234cSJeremy L Thompson 
16849fd234cSJeremy L Thompson   @brief Get the E-vector layout of a CeedElemRestriction
16949fd234cSJeremy L Thompson 
170ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
171ea61e9acSJeremy L Thompson   @param[out] layout  Variable to store layout array, stored as [nodes, components, elements].
172ea61e9acSJeremy 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]
17349fd234cSJeremy L Thompson 
17449fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
17549fd234cSJeremy L Thompson 
17649fd234cSJeremy L Thompson   @ref Backend
17749fd234cSJeremy L Thompson **/
1782b730f8bSJeremy L Thompson int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, CeedInt (*layout)[3]) {
1796574a04fSJeremy L Thompson   CeedCheck(rstr->layout[0], rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no layout data");
1802b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*layout)[i] = rstr->layout[i];
181e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
18249fd234cSJeremy L Thompson }
18349fd234cSJeremy L Thompson 
18449fd234cSJeremy L Thompson /**
18549fd234cSJeremy L Thompson 
18649fd234cSJeremy L Thompson   @brief Set the E-vector layout of a CeedElemRestriction
18749fd234cSJeremy L Thompson 
188ea61e9acSJeremy L Thompson   @param[in] rstr   CeedElemRestriction
189ea61e9acSJeremy L Thompson   @param[in] layout Variable to containing layout array, stored as [nodes, components, elements].
190ea61e9acSJeremy 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]
19149fd234cSJeremy L Thompson 
19249fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
19349fd234cSJeremy L Thompson 
19449fd234cSJeremy L Thompson   @ref Backend
19549fd234cSJeremy L Thompson **/
1962b730f8bSJeremy L Thompson int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
1972b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) rstr->layout[i] = layout[i];
198e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
19949fd234cSJeremy L Thompson }
20049fd234cSJeremy L Thompson 
20149fd234cSJeremy L Thompson /**
2027a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedElemRestriction
2037a982d89SJeremy L. Thompson 
204ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
2057a982d89SJeremy L. Thompson   @param[out] data Variable to store data
2067a982d89SJeremy L. Thompson 
2077a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2087a982d89SJeremy L. Thompson 
2097a982d89SJeremy L. Thompson   @ref Backend
2107a982d89SJeremy L. Thompson **/
211777ff853SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) {
212777ff853SJeremy L Thompson   *(void **)data = rstr->data;
213e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2147a982d89SJeremy L. Thompson }
2157a982d89SJeremy L. Thompson 
2167a982d89SJeremy L. Thompson /**
2177a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedElemRestriction
2187a982d89SJeremy L. Thompson 
219ea61e9acSJeremy L Thompson   @param[in,out] rstr CeedElemRestriction
220ea61e9acSJeremy L Thompson   @param[in]     data Data to set
2217a982d89SJeremy L. Thompson 
2227a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2237a982d89SJeremy L. Thompson 
2247a982d89SJeremy L. Thompson   @ref Backend
2257a982d89SJeremy L. Thompson **/
226777ff853SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) {
227777ff853SJeremy L Thompson   rstr->data = data;
228e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2297a982d89SJeremy L. Thompson }
2307a982d89SJeremy L. Thompson 
23134359f16Sjeremylt /**
23234359f16Sjeremylt   @brief Increment the reference counter for a CeedElemRestriction
23334359f16Sjeremylt 
234ea61e9acSJeremy L Thompson   @param[in,out] rstr ElemRestriction to increment the reference counter
23534359f16Sjeremylt 
23634359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
23734359f16Sjeremylt 
23834359f16Sjeremylt   @ref Backend
23934359f16Sjeremylt **/
2409560d06aSjeremylt int CeedElemRestrictionReference(CeedElemRestriction rstr) {
24134359f16Sjeremylt   rstr->ref_count++;
24234359f16Sjeremylt   return CEED_ERROR_SUCCESS;
24334359f16Sjeremylt }
24434359f16Sjeremylt 
2456e15d496SJeremy L Thompson /**
2466e15d496SJeremy L Thompson   @brief Estimate number of FLOPs required to apply CeedElemRestriction in t_mode
2476e15d496SJeremy L Thompson 
248ea61e9acSJeremy L Thompson   @param[in]  rstr   ElemRestriction to estimate FLOPs for
249ea61e9acSJeremy L Thompson   @param[in]  t_mode Apply restriction or transpose
250ea61e9acSJeremy L Thompson   @param[out] flops  Address of variable to hold FLOPs estimate
2516e15d496SJeremy L Thompson 
2526e15d496SJeremy L Thompson   @ref Backend
2536e15d496SJeremy L Thompson **/
2542b730f8bSJeremy L Thompson int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedSize *flops) {
2556e15d496SJeremy L Thompson   bool    is_oriented;
2562b730f8bSJeremy L Thompson   CeedInt e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp, scale = 0;
2576e15d496SJeremy L Thompson 
2582b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionIsOriented(rstr, &is_oriented));
2596e15d496SJeremy L Thompson   switch (t_mode) {
2602b730f8bSJeremy L Thompson     case CEED_NOTRANSPOSE:
2612b730f8bSJeremy L Thompson       scale = is_oriented ? 1 : 0;
2622b730f8bSJeremy L Thompson       break;
2632b730f8bSJeremy L Thompson     case CEED_TRANSPOSE:
2642b730f8bSJeremy L Thompson       scale = is_oriented ? 2 : 1;
2652b730f8bSJeremy L Thompson       break;
2666e15d496SJeremy L Thompson   }
2676e15d496SJeremy L Thompson   *flops = e_size * scale;
2686e15d496SJeremy L Thompson 
2696e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2706e15d496SJeremy L Thompson }
2716e15d496SJeremy L Thompson 
2727a982d89SJeremy L. Thompson /// @}
2737a982d89SJeremy L. Thompson 
27415910d16Sjeremylt /// @cond DOXYGEN_SKIP
27515910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
27615910d16Sjeremylt /// @endcond
27715910d16Sjeremylt 
2787a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
2797a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
2807a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
2817a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
282d7b241e6Sjeremylt /// @{
283d7b241e6Sjeremylt 
2847a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
28545f1e315Sjeremylt const CeedInt CEED_STRIDES_BACKEND[3] = {0};
2867a982d89SJeremy L. Thompson 
2874cc79fe7SJed Brown /// Indicate that no CeedElemRestriction is provided by the user
2882b730f8bSJeremy L Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = &ceed_elemrestriction_none;
2897a982d89SJeremy L. Thompson 
290d7b241e6Sjeremylt /**
291b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
292d7b241e6Sjeremylt 
293ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
294ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array
295ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
296ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
297ea61e9acSJeremy L Thompson   @param[in]  comp_stride Stride between components for the same L-vector "node".
298ea61e9acSJeremy 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.
299ea61e9acSJeremy L Thompson   @param[in]  l_size      The size of the L-vector.
300ea61e9acSJeremy L Thompson                             This vector may be larger than the elements and fields given by this restriction.
301ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
302ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
303ea61e9acSJeremy L Thompson   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
304ea61e9acSJeremy L Thompson                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
305ea61e9acSJeremy L Thompson 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
306ea61e9acSJeremy L Thompson   @param[out] rstr    Address of the variable where the newly created CeedElemRestriction will be stored
307d7b241e6Sjeremylt 
308b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
309dfdf5a53Sjeremylt 
3107a982d89SJeremy L. Thompson   @ref User
311b11c1e72Sjeremylt **/
3122b730f8bSJeremy L Thompson int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
3132b730f8bSJeremy L Thompson                               CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
3145fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
3155fe0d4faSjeremylt     Ceed delegate;
3166574a04fSJeremy L Thompson 
3172b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
3186574a04fSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ElemRestrictionCreate");
3192b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
320e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
3215fe0d4faSjeremylt   }
3225fe0d4faSjeremylt 
3236574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
3246574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
3256574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
326e022e1f8SJeremy L Thompson 
3272b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
3284ce2993fSjeremylt   (*rstr)->ceed = ceed;
3292b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
330d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
331d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
332d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
333d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
334d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
335d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
336d1d35e2fSjeremylt   (*rstr)->num_blk     = num_elem;
337d1d35e2fSjeremylt   (*rstr)->blk_size    = 1;
3386402da51SJeremy L Thompson   (*rstr)->is_oriented = false;
3392b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, *rstr));
340e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
341d7b241e6Sjeremylt }
342d7b241e6Sjeremylt 
343d7b241e6Sjeremylt /**
344fc0567d9Srezgarshakeri   @brief Create a CeedElemRestriction with orientation sign
345fc0567d9Srezgarshakeri 
346ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
347ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array
348ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
349ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
350ea61e9acSJeremy L Thompson   @param[in]  comp_stride Stride between components for the same L-vector "node".
351ea61e9acSJeremy 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.
352ea61e9acSJeremy L Thompson   @param[in]  l_size      The size of the L-vector.
353ea61e9acSJeremy L Thompson                             This vector may be larger than the elements and fields given by this restriction.
354ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
355ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
356ea61e9acSJeremy L Thompson   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
357ea61e9acSJeremy L Thompson                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
358ea61e9acSJeremy L Thompson 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
359ea61e9acSJeremy 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.
360ea61e9acSJeremy L Thompson   @param[out] rstr       Address of the variable where the newly created CeedElemRestriction will be stored
361fc0567d9Srezgarshakeri 
362fc0567d9Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
363fc0567d9Srezgarshakeri 
364fc0567d9Srezgarshakeri   @ref User
365fc0567d9Srezgarshakeri **/
3662b730f8bSJeremy L Thompson int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
3672b730f8bSJeremy L Thompson                                       CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orient,
368fc0567d9Srezgarshakeri                                       CeedElemRestriction *rstr) {
369c7745053SRezgar Shakeri   if (!ceed->ElemRestrictionCreateOriented) {
370fc0567d9Srezgarshakeri     Ceed delegate;
3716574a04fSJeremy L Thompson 
3722b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
3736574a04fSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateOriented");
3742b730f8bSJeremy L Thompson     CeedCall(
3752b730f8bSJeremy L Thompson         CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, orient, rstr));
376fc0567d9Srezgarshakeri     return CEED_ERROR_SUCCESS;
377fc0567d9Srezgarshakeri   }
378fc0567d9Srezgarshakeri 
3796574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
3806574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
3816574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
382e022e1f8SJeremy L Thompson 
3832b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
384fc0567d9Srezgarshakeri   (*rstr)->ceed = ceed;
3852b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
386fc0567d9Srezgarshakeri   (*rstr)->ref_count   = 1;
387fc0567d9Srezgarshakeri   (*rstr)->num_elem    = num_elem;
388fc0567d9Srezgarshakeri   (*rstr)->elem_size   = elem_size;
389fc0567d9Srezgarshakeri   (*rstr)->num_comp    = num_comp;
390fc0567d9Srezgarshakeri   (*rstr)->comp_stride = comp_stride;
391fc0567d9Srezgarshakeri   (*rstr)->l_size      = l_size;
392fc0567d9Srezgarshakeri   (*rstr)->num_blk     = num_elem;
393fc0567d9Srezgarshakeri   (*rstr)->blk_size    = 1;
3946402da51SJeremy L Thompson   (*rstr)->is_oriented = true;
3952b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateOriented(mem_type, copy_mode, offsets, orient, *rstr));
396fc0567d9Srezgarshakeri   return CEED_ERROR_SUCCESS;
397fc0567d9Srezgarshakeri }
398fc0567d9Srezgarshakeri 
399fc0567d9Srezgarshakeri /**
4007509a596Sjeremylt   @brief Create a strided CeedElemRestriction
401d7b241e6Sjeremylt 
402ea61e9acSJeremy L Thompson   @param[in]  ceed      Ceed object where the CeedElemRestriction will be created
403ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
404ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
405ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation "node" (1 for scalar fields)
406ea61e9acSJeremy L Thompson   @param[in]  l_size    The size of the L-vector.
407ea61e9acSJeremy L Thompson                           This vector may be larger than the elements and fields given by this restriction.
408ea61e9acSJeremy L Thompson   @param[in]  strides   Array for strides between [nodes, components, elements].
409ea61e9acSJeremy 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].
410ea61e9acSJeremy L Thompson                           @a CEED_STRIDES_BACKEND may be used with vectors created by a Ceed backend.
411ea61e9acSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created CeedElemRestriction will be stored
412d7b241e6Sjeremylt 
413b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
414dfdf5a53Sjeremylt 
4157a982d89SJeremy L. Thompson   @ref User
416b11c1e72Sjeremylt **/
4172b730f8bSJeremy L Thompson int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedSize l_size, const CeedInt strides[3],
418f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
4195fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
4205fe0d4faSjeremylt     Ceed delegate;
421b04eb3d9SSebastian Grimberg 
4222b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
4236402da51SJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ElemRestrictionCreateStrided");
4242b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, l_size, strides, rstr));
425e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
4265fe0d4faSjeremylt   }
4275fe0d4faSjeremylt 
4286574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
4296574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
430e022e1f8SJeremy L Thompson 
4312b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
4324ce2993fSjeremylt   (*rstr)->ceed = ceed;
4332b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
434d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
435d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
436d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
437d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
438d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
439d1d35e2fSjeremylt   (*rstr)->num_blk     = num_elem;
440d1d35e2fSjeremylt   (*rstr)->blk_size    = 1;
4416402da51SJeremy L Thompson   (*rstr)->is_oriented = false;
4422b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
4432b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
4442b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, *rstr));
445e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
446d7b241e6Sjeremylt }
447d7b241e6Sjeremylt 
448d7b241e6Sjeremylt /**
449b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
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 in the @a offsets array.
453ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of unknowns) per element
454ea61e9acSJeremy L Thompson   @param[in]  blk_size    Number of elements in a block
455ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
456ea61e9acSJeremy L Thompson   @param[in]  comp_stride Stride between components for the same L-vector "node".
457ea61e9acSJeremy 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.
458ea61e9acSJeremy L Thompson   @param[in]  l_size      The size of the L-vector.
459ea61e9acSJeremy L Thompson                             This vector may be larger than the elements and fields given by this restriction.
460ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
461ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
462ea61e9acSJeremy L Thompson   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
463ea61e9acSJeremy L Thompson                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
464ea61e9acSJeremy 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
465ea61e9acSJeremy L Thompson  the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
466ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
467d7b241e6Sjeremylt 
468b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
469dfdf5a53Sjeremylt 
4707a982d89SJeremy L. Thompson   @ref Backend
471b11c1e72Sjeremylt  **/
4722b730f8bSJeremy L Thompson int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedInt comp_stride,
4732b730f8bSJeremy L Thompson                                      CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets,
4744ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
475d1d35e2fSjeremylt   CeedInt *blk_offsets;
476d1d35e2fSjeremylt   CeedInt  num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
477d7b241e6Sjeremylt 
4785fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
4795fe0d4faSjeremylt     Ceed delegate;
4806574a04fSJeremy L Thompson 
4812b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
4826402da51SJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
4832b730f8bSJeremy L Thompson     CeedCall(
4842b730f8bSJeremy L Thompson         CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, blk_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
485e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
4865fe0d4faSjeremylt   }
487d7b241e6Sjeremylt 
4886574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
4896574a04fSJeremy L Thompson   CeedCheck(blk_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
4906574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
4916574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
492e022e1f8SJeremy L Thompson 
4932b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
494d7b241e6Sjeremylt 
4952b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(num_blk * blk_size * elem_size, &blk_offsets));
4962b730f8bSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size, elem_size));
497d7b241e6Sjeremylt 
4984ce2993fSjeremylt   (*rstr)->ceed = ceed;
4992b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
500d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
501d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
502d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
503d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
504d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
505d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
506d1d35e2fSjeremylt   (*rstr)->num_blk     = num_blk;
507d1d35e2fSjeremylt   (*rstr)->blk_size    = blk_size;
5086402da51SJeremy L Thompson   (*rstr)->is_oriented = false;
5092b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)blk_offsets, *rstr));
510d1d35e2fSjeremylt   if (copy_mode == CEED_OWN_POINTER) {
5112b730f8bSJeremy L Thompson     CeedCall(CeedFree(&offsets));
5121d102b48SJeremy L Thompson   }
513e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
514d7b241e6Sjeremylt }
515d7b241e6Sjeremylt 
516b11c1e72Sjeremylt /**
5177509a596Sjeremylt   @brief Create a blocked strided CeedElemRestriction
5187509a596Sjeremylt 
519ea61e9acSJeremy L Thompson   @param[in]  ceed      Ceed object where the CeedElemRestriction will be created
520ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
521ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
522ea61e9acSJeremy L Thompson   @param[in]  blk_size  Number of elements in a block
523ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation node (1 for scalar fields)
524ea61e9acSJeremy L Thompson   @param[in]  l_size    The size of the L-vector.
525ea61e9acSJeremy L Thompson                           This vector may be larger than the elements and fields given by this restriction.
526ea61e9acSJeremy L Thompson   @param[in]  strides   Array for strides between [nodes, components, elements].
527ea61e9acSJeremy 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].
528ea61e9acSJeremy L Thompson                           @a CEED_STRIDES_BACKEND may be used with vectors created by a Ceed backend.
529ea61e9acSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created CeedElemRestriction will be stored
5307509a596Sjeremylt 
5317509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
5327509a596Sjeremylt 
5337a982d89SJeremy L. Thompson   @ref User
5347509a596Sjeremylt **/
5352b730f8bSJeremy L Thompson int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedSize l_size,
5368621c6c6SJeremy L Thompson                                             const CeedInt strides[3], CeedElemRestriction *rstr) {
537d1d35e2fSjeremylt   CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
5387509a596Sjeremylt 
5397509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
5407509a596Sjeremylt     Ceed delegate;
5416574a04fSJeremy L Thompson 
5422b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
5436402da51SJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlockedStrided");
5442b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, blk_size, num_comp, l_size, strides, rstr));
545e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
5467509a596Sjeremylt   }
5477509a596Sjeremylt 
5486574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
5496574a04fSJeremy L Thompson   CeedCheck(blk_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
5506574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
551e022e1f8SJeremy L Thompson 
5522b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
5537509a596Sjeremylt 
5547509a596Sjeremylt   (*rstr)->ceed = ceed;
5552b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
556d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
557d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
558d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
559d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
560d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
561d1d35e2fSjeremylt   (*rstr)->num_blk     = num_blk;
562d1d35e2fSjeremylt   (*rstr)->blk_size    = blk_size;
5636402da51SJeremy L Thompson   (*rstr)->is_oriented = false;
5642b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
5652b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
5662b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, *rstr));
567e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5687509a596Sjeremylt }
5697509a596Sjeremylt 
5707509a596Sjeremylt /**
571*c17ec2beSJeremy L Thompson   @brief Copy the pointer to a CeedElemRestriction and set `CeedElemRestrictionApply()` implementation to `CeedElemRestrictionApplyUnsigned()`.
572*c17ec2beSJeremy L Thompson 
573*c17ec2beSJeremy L Thompson   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
574*c17ec2beSJeremy L Thompson 
575*c17ec2beSJeremy L Thompson   @param[in]     rstr          CeedElemRestriction to create unsigned reference to
576*c17ec2beSJeremy L Thompson   @param[in,out] rstr_unsigned Variable to store unsigned CeedElemRestriction
577*c17ec2beSJeremy L Thompson 
578*c17ec2beSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
579*c17ec2beSJeremy L Thompson 
580*c17ec2beSJeremy L Thompson   @ref User
581*c17ec2beSJeremy L Thompson **/
582*c17ec2beSJeremy L Thompson int CeedElemRestrictionCreateUnsignedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unsigned) {
583*c17ec2beSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr_unsigned));
584*c17ec2beSJeremy L Thompson 
585*c17ec2beSJeremy L Thompson   // Copy old rstr
586*c17ec2beSJeremy L Thompson   memcpy(*rstr_unsigned, rstr, sizeof(struct CeedElemRestriction_private));
587*c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ceed = NULL;
588*c17ec2beSJeremy L Thompson   CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unsigned)->ceed));
589*c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ref_count = 1;
590*c17ec2beSJeremy L Thompson   (*rstr_unsigned)->strides   = NULL;
591*c17ec2beSJeremy L Thompson   if (rstr->strides) {
592*c17ec2beSJeremy L Thompson     CeedCall(CeedMalloc(3, &(*rstr_unsigned)->strides));
593*c17ec2beSJeremy L Thompson     for (CeedInt i = 0; i < 3; i++) (*rstr_unsigned)->strides[i] = rstr->strides[i];
594*c17ec2beSJeremy L Thompson   }
595*c17ec2beSJeremy L Thompson   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unsigned)->rstr_signed));
596*c17ec2beSJeremy L Thompson 
597*c17ec2beSJeremy L Thompson   // Override Apply
598*c17ec2beSJeremy L Thompson   (*rstr_unsigned)->Apply = rstr->ApplyUnsigned;
599*c17ec2beSJeremy L Thompson 
600*c17ec2beSJeremy L Thompson   return CEED_ERROR_SUCCESS;
601*c17ec2beSJeremy L Thompson }
602*c17ec2beSJeremy L Thompson 
603*c17ec2beSJeremy L Thompson /**
604ea61e9acSJeremy L Thompson   @brief Copy the pointer to a CeedElemRestriction.
6059fd66db6SSebastian Grimberg 
606ea61e9acSJeremy L Thompson   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
6079560d06aSjeremylt 
6089fd66db6SSebastian 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.
6099fd66db6SSebastian Grimberg         This CeedElemRestriction will be destroyed if `rstr_copy` is the only reference to this CeedElemRestriction.
610ea61e9acSJeremy L Thompson 
611ea61e9acSJeremy L Thompson   @param[in]     rstr      CeedElemRestriction to copy reference to
612ea61e9acSJeremy L Thompson   @param[in,out] rstr_copy Variable to store copied reference
6139560d06aSjeremylt 
6149560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
6159560d06aSjeremylt 
6169560d06aSjeremylt   @ref User
6179560d06aSjeremylt **/
6182b730f8bSJeremy L Thompson int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_copy) {
619393ac2cdSJeremy L Thompson   if (rstr != CEED_ELEMRESTRICTION_NONE) CeedCall(CeedElemRestrictionReference(rstr));
6202b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionDestroy(rstr_copy));
6219560d06aSjeremylt   *rstr_copy = rstr;
6229560d06aSjeremylt   return CEED_ERROR_SUCCESS;
6239560d06aSjeremylt }
6249560d06aSjeremylt 
6259560d06aSjeremylt /**
626b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
627b11c1e72Sjeremylt 
628ea61e9acSJeremy L Thompson   @param[in]  rstr  CeedElemRestriction
629ea61e9acSJeremy L Thompson   @param[out] l_vec The address of the L-vector to be created, or NULL
630ea61e9acSJeremy L Thompson   @param[out] e_vec The address of the E-vector to be created, or NULL
631b11c1e72Sjeremylt 
632b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
633dfdf5a53Sjeremylt 
6347a982d89SJeremy L. Thompson   @ref User
635b11c1e72Sjeremylt **/
6362b730f8bSJeremy L Thompson int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, CeedVector *e_vec) {
637d2643443SJeremy L Thompson   CeedSize e_size, l_size;
638d1d35e2fSjeremylt   l_size = rstr->l_size;
639d1d35e2fSjeremylt   e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
6402b730f8bSJeremy L Thompson   if (l_vec) CeedCall(CeedVectorCreate(rstr->ceed, l_size, l_vec));
6412b730f8bSJeremy L Thompson   if (e_vec) CeedCall(CeedVectorCreate(rstr->ceed, e_size, e_vec));
642e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
643d7b241e6Sjeremylt }
644d7b241e6Sjeremylt 
645d7b241e6Sjeremylt /**
646d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
647d7b241e6Sjeremylt 
648ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
649ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
650ea61e9acSJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
651ea61e9acSJeremy L Thompson   @param[out] ru      Output vector (of shape [@a num_elem * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
652ea61e9acSJeremy L Thompson                         Ordering of the e-vector is decided by the backend.
653ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
654b11c1e72Sjeremylt 
655b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
656dfdf5a53Sjeremylt 
6577a982d89SJeremy L. Thompson   @ref User
658b11c1e72Sjeremylt **/
6592b730f8bSJeremy L Thompson int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
660d7b241e6Sjeremylt   CeedInt m, n;
661d7b241e6Sjeremylt 
662d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
663d1d35e2fSjeremylt     m = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
664d1d35e2fSjeremylt     n = rstr->l_size;
665d7b241e6Sjeremylt   } else {
666d1d35e2fSjeremylt     m = rstr->l_size;
667d1d35e2fSjeremylt     n = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
668d7b241e6Sjeremylt   }
6696574a04fSJeremy L Thompson   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
6706574a04fSJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
6716574a04fSJeremy L Thompson   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
6726574a04fSJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
6732b730f8bSJeremy L Thompson   if (rstr->num_elem > 0) CeedCall(rstr->Apply(rstr, t_mode, u, ru, request));
674e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
675d7b241e6Sjeremylt }
676d7b241e6Sjeremylt 
677d7b241e6Sjeremylt /**
678f30b1135SSebastian Grimberg   @brief Restrict an L-vector to an E-vector or apply its transpose ignoring any
679f30b1135SSebastian Grimberg          provided orientations
680f30b1135SSebastian Grimberg 
681f30b1135SSebastian Grimberg   @param[in]  rstr    CeedElemRestriction
682f30b1135SSebastian Grimberg   @param[in]  t_mode  Apply restriction or transpose
683f30b1135SSebastian Grimberg   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
684f30b1135SSebastian Grimberg   @param[out] ru      Output vector (of shape [@a num_elem * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
685f30b1135SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
686f30b1135SSebastian Grimberg   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
687f30b1135SSebastian Grimberg 
688f30b1135SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
689f30b1135SSebastian Grimberg 
690f30b1135SSebastian Grimberg   @ref User
691f30b1135SSebastian Grimberg **/
692f30b1135SSebastian Grimberg int CeedElemRestrictionApplyUnsigned(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
693f30b1135SSebastian Grimberg   CeedInt m, n;
694f30b1135SSebastian Grimberg 
695b04eb3d9SSebastian Grimberg   CeedCheck(rstr->ApplyUnsigned, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ElemRestrictionApplyUnsigned");
696b17517eeSSebastian Grimberg 
697f30b1135SSebastian Grimberg   if (t_mode == CEED_NOTRANSPOSE) {
698f30b1135SSebastian Grimberg     m = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
699f30b1135SSebastian Grimberg     n = rstr->l_size;
700f30b1135SSebastian Grimberg   } else {
701f30b1135SSebastian Grimberg     m = rstr->l_size;
702f30b1135SSebastian Grimberg     n = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
703f30b1135SSebastian Grimberg   }
704c7be5f81SSebastian Grimberg   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
705c7be5f81SSebastian Grimberg             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
706c7be5f81SSebastian Grimberg   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
707c7be5f81SSebastian Grimberg             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
708b17517eeSSebastian Grimberg   if (rstr->num_elem > 0) CeedCall(rstr->ApplyUnsigned(rstr, t_mode, u, ru, request));
709f30b1135SSebastian Grimberg   return CEED_ERROR_SUCCESS;
710f30b1135SSebastian Grimberg }
711f30b1135SSebastian Grimberg 
712f30b1135SSebastian Grimberg /**
713d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
714be9261b7Sjeremylt 
715ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
716ea61e9acSJeremy 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
717ea61e9acSJeremy L Thompson : 4*blk_size]
718ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
719ea61e9acSJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
720ea61e9acSJeremy L Thompson   @param[out] ru      Output vector (of shape [@a blk_size * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
721ea61e9acSJeremy L Thompson                         Ordering of the e-vector is decided by the backend.
722ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
723be9261b7Sjeremylt 
724be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
725be9261b7Sjeremylt 
7267a982d89SJeremy L. Thompson   @ref Backend
727be9261b7Sjeremylt **/
7282b730f8bSJeremy L Thompson int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
7292b730f8bSJeremy L Thompson                                   CeedRequest *request) {
730be9261b7Sjeremylt   CeedInt m, n;
731be9261b7Sjeremylt 
7326402da51SJeremy L Thompson   CeedCheck(rstr->ApplyBlock, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionApplyBlock");
7336402da51SJeremy L Thompson 
734d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
735d1d35e2fSjeremylt     m = rstr->blk_size * rstr->elem_size * rstr->num_comp;
736d1d35e2fSjeremylt     n = rstr->l_size;
737be9261b7Sjeremylt   } else {
738d1d35e2fSjeremylt     m = rstr->l_size;
739d1d35e2fSjeremylt     n = rstr->blk_size * rstr->elem_size * rstr->num_comp;
740be9261b7Sjeremylt   }
7416574a04fSJeremy L Thompson   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
7426574a04fSJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
7436574a04fSJeremy L Thompson   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
7446574a04fSJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
7456574a04fSJeremy L Thompson   CeedCheck(rstr->blk_size * block <= rstr->num_elem, rstr->ceed, CEED_ERROR_DIMENSION,
7466574a04fSJeremy L Thompson             "Cannot retrieve block %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", block, rstr->blk_size * block,
7476574a04fSJeremy L Thompson             rstr->num_elem);
7482b730f8bSJeremy L Thompson   CeedCall(rstr->ApplyBlock(rstr, block, t_mode, u, ru, request));
749e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
750be9261b7Sjeremylt }
751be9261b7Sjeremylt 
752be9261b7Sjeremylt /**
753b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedElemRestriction
754b7c9bbdaSJeremy L Thompson 
755ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
756b7c9bbdaSJeremy L Thompson   @param[out] ceed Variable to store Ceed
757b7c9bbdaSJeremy L Thompson 
758b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
759b7c9bbdaSJeremy L Thompson 
760b7c9bbdaSJeremy L Thompson   @ref Advanced
761b7c9bbdaSJeremy L Thompson **/
762b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
763b7c9bbdaSJeremy L Thompson   *ceed = rstr->ceed;
764b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
765b7c9bbdaSJeremy L Thompson }
766b7c9bbdaSJeremy L Thompson 
767b7c9bbdaSJeremy L Thompson /**
768d979a051Sjeremylt   @brief Get the L-vector component stride
769a681ae63Sjeremylt 
770ea61e9acSJeremy L Thompson   @param[in]  rstr        CeedElemRestriction
771d1d35e2fSjeremylt   @param[out] comp_stride Variable to store component stride
772a681ae63Sjeremylt 
773a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
774a681ae63Sjeremylt 
775b7c9bbdaSJeremy L Thompson   @ref Advanced
776a681ae63Sjeremylt **/
7772b730f8bSJeremy L Thompson int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, CeedInt *comp_stride) {
778d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
779e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
780a681ae63Sjeremylt }
781a681ae63Sjeremylt 
782a681ae63Sjeremylt /**
783a681ae63Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
784a681ae63Sjeremylt 
785ea61e9acSJeremy L Thompson   @param[in] rstr      CeedElemRestriction
786d1d35e2fSjeremylt   @param[out] num_elem Variable to store number of elements
787a681ae63Sjeremylt 
788a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
789a681ae63Sjeremylt 
790b7c9bbdaSJeremy L Thompson   @ref Advanced
791a681ae63Sjeremylt **/
7922b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, CeedInt *num_elem) {
793d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
794e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
795a681ae63Sjeremylt }
796a681ae63Sjeremylt 
797a681ae63Sjeremylt /**
798a681ae63Sjeremylt   @brief Get the size of elements in the CeedElemRestriction
799a681ae63Sjeremylt 
800ea61e9acSJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
801d1d35e2fSjeremylt   @param[out] elem_size Variable to store size of elements
802a681ae63Sjeremylt 
803a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
804a681ae63Sjeremylt 
805b7c9bbdaSJeremy L Thompson   @ref Advanced
806a681ae63Sjeremylt **/
8072b730f8bSJeremy L Thompson int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, CeedInt *elem_size) {
808d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
809e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
810a681ae63Sjeremylt }
811a681ae63Sjeremylt 
812a681ae63Sjeremylt /**
813d979a051Sjeremylt   @brief Get the size of the l-vector for a CeedElemRestriction
814a681ae63Sjeremylt 
815ea61e9acSJeremy L Thompson   @param[in]  rstr   CeedElemRestriction
816d1d35e2fSjeremylt   @param[out] l_size Variable to store number of nodes
817a681ae63Sjeremylt 
818a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
819a681ae63Sjeremylt 
820b7c9bbdaSJeremy L Thompson   @ref Advanced
821a681ae63Sjeremylt **/
8222b730f8bSJeremy L Thompson int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, CeedSize *l_size) {
823d1d35e2fSjeremylt   *l_size = rstr->l_size;
824e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
825a681ae63Sjeremylt }
826a681ae63Sjeremylt 
827a681ae63Sjeremylt /**
828ea61e9acSJeremy L Thompson   @brief Get the number of components in the elements of a CeedElemRestriction
829a681ae63Sjeremylt 
830ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction
831d1d35e2fSjeremylt   @param[out] num_comp Variable to store number of components
832a681ae63Sjeremylt 
833a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
834a681ae63Sjeremylt 
835b7c9bbdaSJeremy L Thompson   @ref Advanced
836a681ae63Sjeremylt **/
8372b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, CeedInt *num_comp) {
838d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
839e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
840a681ae63Sjeremylt }
841a681ae63Sjeremylt 
842a681ae63Sjeremylt /**
843a681ae63Sjeremylt   @brief Get the number of blocks in a CeedElemRestriction
844a681ae63Sjeremylt 
845ea61e9acSJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
846d1d35e2fSjeremylt   @param[out] num_block Variable to store number of blocks
847a681ae63Sjeremylt 
848a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
849a681ae63Sjeremylt 
850b7c9bbdaSJeremy L Thompson   @ref Advanced
851a681ae63Sjeremylt **/
8522b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, CeedInt *num_block) {
853d1d35e2fSjeremylt   *num_block = rstr->num_blk;
854e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
855a681ae63Sjeremylt }
856a681ae63Sjeremylt 
857a681ae63Sjeremylt /**
858a681ae63Sjeremylt   @brief Get the size of blocks in the CeedElemRestriction
859a681ae63Sjeremylt 
860ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction
861d1d35e2fSjeremylt   @param[out] blk_size Variable to store size of blocks
862a681ae63Sjeremylt 
863a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
864a681ae63Sjeremylt 
865b7c9bbdaSJeremy L Thompson   @ref Advanced
866a681ae63Sjeremylt **/
8672b730f8bSJeremy L Thompson int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, CeedInt *blk_size) {
868d1d35e2fSjeremylt   *blk_size = rstr->blk_size;
869e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
870a681ae63Sjeremylt }
871a681ae63Sjeremylt 
872a681ae63Sjeremylt /**
873d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
8741469ee4dSjeremylt 
875ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
876d1d35e2fSjeremylt   @param[out] mult Vector to store multiplicity (of size l_size)
8771469ee4dSjeremylt 
8781469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
8791469ee4dSjeremylt 
8807a982d89SJeremy L. Thompson   @ref User
8811469ee4dSjeremylt **/
8822b730f8bSJeremy L Thompson int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, CeedVector mult) {
883d1d35e2fSjeremylt   CeedVector e_vec;
8841469ee4dSjeremylt 
88525509ebbSRezgar Shakeri   // Create e_vec to hold intermediate computation in E^T (E 1)
8862b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionCreateVector(rstr, NULL, &e_vec));
8871469ee4dSjeremylt 
88825509ebbSRezgar Shakeri   // Compute e_vec = E * 1
8892b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 1.0));
8902b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, CEED_REQUEST_IMMEDIATE));
89125509ebbSRezgar Shakeri   // Compute multiplicity, mult = E^T * e_vec = E^T (E 1)
8922b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 0.0));
8932b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, CEED_REQUEST_IMMEDIATE));
8941469ee4dSjeremylt   // Cleanup
8952b730f8bSJeremy L Thompson   CeedCall(CeedVectorDestroy(&e_vec));
896e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
8971469ee4dSjeremylt }
8981469ee4dSjeremylt 
8991469ee4dSjeremylt /**
900f02ca4a2SJed Brown   @brief View a CeedElemRestriction
901f02ca4a2SJed Brown 
902f02ca4a2SJed Brown   @param[in] rstr   CeedElemRestriction to view
903f02ca4a2SJed Brown   @param[in] stream Stream to write; typically stdout/stderr or a file
904f02ca4a2SJed Brown 
905f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
906f02ca4a2SJed Brown 
9077a982d89SJeremy L. Thompson   @ref User
908f02ca4a2SJed Brown **/
909f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
9107509a596Sjeremylt   char stridesstr[500];
9112b730f8bSJeremy L Thompson   if (rstr->strides) {
9122b730f8bSJeremy L Thompson     sprintf(stridesstr, "[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "]", rstr->strides[0], rstr->strides[1], rstr->strides[2]);
9132b730f8bSJeremy L Thompson   } else {
914990fdeb6SJeremy L Thompson     sprintf(stridesstr, "%" CeedInt_FMT, rstr->comp_stride);
9152b730f8bSJeremy L Thompson   }
9167509a596Sjeremylt 
9172b730f8bSJeremy L Thompson   fprintf(stream, "%sCeedElemRestriction from (%td, %" CeedInt_FMT ") to %" CeedInt_FMT " elements with %" CeedInt_FMT " nodes each and %s %s\n",
9182b730f8bSJeremy L Thompson           rstr->blk_size > 1 ? "Blocked " : "", rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
919d979a051Sjeremylt           rstr->strides ? "strides" : "component stride", stridesstr);
920e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
921f02ca4a2SJed Brown }
922f02ca4a2SJed Brown 
923f02ca4a2SJed Brown /**
924b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
925b11c1e72Sjeremylt 
926ea61e9acSJeremy L Thompson   @param[in,out] rstr CeedElemRestriction to destroy
927b11c1e72Sjeremylt 
928b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
929dfdf5a53Sjeremylt 
9307a982d89SJeremy L. Thompson   @ref User
931b11c1e72Sjeremylt **/
9324ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
933393ac2cdSJeremy L Thompson   if (!*rstr || *rstr == CEED_ELEMRESTRICTION_NONE || --(*rstr)->ref_count > 0) {
934ad6481ceSJeremy L Thompson     *rstr = NULL;
935ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
936ad6481ceSJeremy L Thompson   }
9376574a04fSJeremy L Thompson   CeedCheck((*rstr)->num_readers == 0, (*rstr)->ceed, CEED_ERROR_ACCESS,
9386574a04fSJeremy L Thompson             "Cannot destroy CeedElemRestriction, a process has read access to the offset data");
939*c17ec2beSJeremy L Thompson 
940*c17ec2beSJeremy L Thompson   // Only destroy backend data once between rstr and unsigned copy
941*c17ec2beSJeremy L Thompson   if ((*rstr)->rstr_signed) CeedCall(CeedElemRestrictionDestroy(&(*rstr)->rstr_signed));
942*c17ec2beSJeremy L Thompson   else if ((*rstr)->Destroy) CeedCall((*rstr)->Destroy(*rstr));
943*c17ec2beSJeremy L Thompson 
9442b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*rstr)->strides));
9452b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*rstr)->ceed));
9462b730f8bSJeremy L Thompson   CeedCall(CeedFree(rstr));
947e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
948d7b241e6Sjeremylt }
949d7b241e6Sjeremylt 
950d7b241e6Sjeremylt /// @}
951