xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-elemrestriction.c (revision 9d36ca5098a5cdf0ec02c0eb5de06d03bc121296)
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 
8ec3da8bcSJed Brown #include <ceed/ceed.h>
9ec3da8bcSJed Brown #include <ceed/backend.h>
103d576824SJeremy L Thompson #include <ceed-impl.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 
26d1d35e2fSjeremylt   @param offsets     Array of shape [@a num_elem, @a elem_size]. Row i holds the
27d979a051Sjeremylt                        ordered list of the offsets (into the input CeedVector)
287a982d89SJeremy L. Thompson                        for the unknowns corresponding to element i, where
29d1d35e2fSjeremylt                        0 <= i < @a num_elem. All offsets must be in the range
30d1d35e2fSjeremylt                        [0, @a l_size - 1].
31d1d35e2fSjeremylt   @param blk_offsets Array of permuted and padded offsets of
32d1d35e2fSjeremylt                        shape [@a num_blk, @a elem_size, @a blk_size].
33d1d35e2fSjeremylt   @param num_blk     Number of blocks
34d1d35e2fSjeremylt   @param num_elem    Number of elements
35d1d35e2fSjeremylt   @param blk_size    Number of elements in a block
36d1d35e2fSjeremylt   @param elem_size   Size of each element
377a982d89SJeremy L. Thompson 
387a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
397a982d89SJeremy L. Thompson 
407a982d89SJeremy L. Thompson   @ref Utility
417a982d89SJeremy L. Thompson **/
42d1d35e2fSjeremylt int CeedPermutePadOffsets(const CeedInt *offsets, CeedInt *blk_offsets,
43d1d35e2fSjeremylt                           CeedInt num_blk, CeedInt num_elem, CeedInt blk_size,
44d1d35e2fSjeremylt                           CeedInt elem_size) {
45d1d35e2fSjeremylt   for (CeedInt e=0; e<num_blk*blk_size; e+=blk_size)
46d1d35e2fSjeremylt     for (int j=0; j<blk_size; j++)
47d1d35e2fSjeremylt       for (int k=0; k<elem_size; k++)
48d1d35e2fSjeremylt         blk_offsets[e*elem_size + k*blk_size + j]
49d1d35e2fSjeremylt           = offsets[CeedIntMin(e+j,num_elem-1)*elem_size + k];
50e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
517a982d89SJeremy L. Thompson }
527a982d89SJeremy L. Thompson 
537a982d89SJeremy L. Thompson /// @}
547a982d89SJeremy L. Thompson 
557a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
567a982d89SJeremy L. Thompson /// CeedElemRestriction Backend API
577a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
587a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionBackend
597a982d89SJeremy L. Thompson /// @{
607a982d89SJeremy L. Thompson 
617a982d89SJeremy L. Thompson /**
62a681ae63Sjeremylt 
63a681ae63Sjeremylt   @brief Get the strides of a strided CeedElemRestriction
647a982d89SJeremy L. Thompson 
657a982d89SJeremy L. Thompson   @param rstr          CeedElemRestriction
66a681ae63Sjeremylt   @param[out] strides  Variable to store strides array
677a982d89SJeremy L. Thompson 
687a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
697a982d89SJeremy L. Thompson 
707a982d89SJeremy L. Thompson   @ref Backend
717a982d89SJeremy L. Thompson **/
72a681ae63Sjeremylt int CeedElemRestrictionGetStrides(CeedElemRestriction rstr,
73a681ae63Sjeremylt                                   CeedInt (*strides)[3]) {
74a681ae63Sjeremylt   if (!rstr->strides)
75a681ae63Sjeremylt     // LCOV_EXCL_START
76e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_MINOR,
77e15f9bd0SJeremy L Thompson                      "ElemRestriction has no stride data");
78a681ae63Sjeremylt   // LCOV_EXCL_STOP
79a681ae63Sjeremylt 
80a681ae63Sjeremylt   for (int i=0; i<3; i++)
81a681ae63Sjeremylt     (*strides)[i] = rstr->strides[i];
82e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
837a982d89SJeremy L. Thompson }
847a982d89SJeremy L. Thompson 
857a982d89SJeremy L. Thompson /**
86bd33150aSjeremylt   @brief Get read-only access to a CeedElemRestriction offsets array by memtype
87bd33150aSjeremylt 
88bd33150aSjeremylt   @param rstr          CeedElemRestriction to retrieve offsets
89d1d35e2fSjeremylt   @param mem_type      Memory type on which to access the array.  If the backend
90bd33150aSjeremylt                          uses a different memory type, this will perform a copy
91bd33150aSjeremylt                          (possibly cached).
92d1d35e2fSjeremylt   @param[out] offsets  Array on memory type mem_type
93bd33150aSjeremylt 
94bd33150aSjeremylt   @return An error code: 0 - success, otherwise - failure
95bd33150aSjeremylt 
96bd33150aSjeremylt   @ref User
97bd33150aSjeremylt **/
98d1d35e2fSjeremylt int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr,
99d1d35e2fSjeremylt                                   CeedMemType mem_type,
100bd33150aSjeremylt                                   const CeedInt **offsets) {
101bd33150aSjeremylt   int ierr;
102bd33150aSjeremylt 
103bd33150aSjeremylt   if (!rstr->GetOffsets)
104bd33150aSjeremylt     // LCOV_EXCL_START
105e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_UNSUPPORTED,
106e15f9bd0SJeremy L Thompson                      "Backend does not support GetOffsets");
107bd33150aSjeremylt   // LCOV_EXCL_STOP
108bd33150aSjeremylt 
109d1d35e2fSjeremylt   ierr = rstr->GetOffsets(rstr, mem_type, offsets); CeedChk(ierr);
110d1d35e2fSjeremylt   rstr->num_readers++;
111e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
112430758c8SJeremy L Thompson }
113430758c8SJeremy L Thompson 
114430758c8SJeremy L Thompson /**
115430758c8SJeremy L Thompson   @brief Restore an offsets array obtained using CeedElemRestrictionGetOffsets()
116430758c8SJeremy L Thompson 
117430758c8SJeremy L Thompson   @param rstr     CeedElemRestriction to restore
118430758c8SJeremy L Thompson   @param offsets  Array of offset data
119430758c8SJeremy L Thompson 
120430758c8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
121430758c8SJeremy L Thompson 
122430758c8SJeremy L Thompson   @ref User
123430758c8SJeremy L Thompson **/
124430758c8SJeremy L Thompson int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr,
125430758c8SJeremy L Thompson                                       const CeedInt **offsets) {
126430758c8SJeremy L Thompson   *offsets = NULL;
127d1d35e2fSjeremylt   rstr->num_readers--;
128e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
129bd33150aSjeremylt }
130bd33150aSjeremylt 
131bd33150aSjeremylt /**
1323ac43b2cSJeremy L Thompson   @brief Get the strided status of a CeedElemRestriction
1333ac43b2cSJeremy L Thompson 
1343ac43b2cSJeremy L Thompson   @param rstr             CeedElemRestriction
135d1d35e2fSjeremylt   @param[out] is_strided  Variable to store strided status, 1 if strided else 0
1363ac43b2cSJeremy L Thompson 
1373ac43b2cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1383ac43b2cSJeremy L Thompson 
1393ac43b2cSJeremy L Thompson   @ref Backend
1403ac43b2cSJeremy L Thompson **/
141d1d35e2fSjeremylt int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) {
142d1d35e2fSjeremylt   *is_strided = rstr->strides ? true : false;
143e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1443ac43b2cSJeremy L Thompson }
1453ac43b2cSJeremy L Thompson 
1463ac43b2cSJeremy L Thompson /**
147b435c5a6Srezgarshakeri   @brief Get oriented status of a CeedElemRestriction
148b435c5a6Srezgarshakeri 
149b435c5a6Srezgarshakeri   @param rstr             CeedElemRestriction
150b435c5a6Srezgarshakeri   @param[out] is_oriented  Variable to store oriented status, 1 if oriented else 0
151b435c5a6Srezgarshakeri 
152b435c5a6Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
153b435c5a6Srezgarshakeri 
154b435c5a6Srezgarshakeri   @ref Backend
155b435c5a6Srezgarshakeri **/
156b435c5a6Srezgarshakeri int CeedElemRestrictionIsOriented(CeedElemRestriction rstr, bool *is_oriented) {
157b435c5a6Srezgarshakeri   *is_oriented = rstr->is_oriented;
158b435c5a6Srezgarshakeri   return CEED_ERROR_SUCCESS;
159b435c5a6Srezgarshakeri }
160b435c5a6Srezgarshakeri 
161b435c5a6Srezgarshakeri /**
162a681ae63Sjeremylt   @brief Get the backend stride status of a CeedElemRestriction
1637a982d89SJeremy L. Thompson 
1647a982d89SJeremy L. Thompson   @param rstr                      CeedElemRestriction
16596b902e2Sjeremylt   @param[out] has_backend_strides  Variable to store stride status
1667a982d89SJeremy L. Thompson 
1677a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1687a982d89SJeremy L. Thompson 
1697a982d89SJeremy L. Thompson   @ref Backend
1707a982d89SJeremy L. Thompson **/
171fd364f38SJeremy L Thompson int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr,
172d1d35e2fSjeremylt     bool *has_backend_strides) {
173a681ae63Sjeremylt   if (!rstr->strides)
174a681ae63Sjeremylt     // LCOV_EXCL_START
175e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_MINOR,
176e15f9bd0SJeremy L Thompson                      "ElemRestriction has no stride data");
177a681ae63Sjeremylt   // LCOV_EXCL_STOP
1787a982d89SJeremy L. Thompson 
179d1d35e2fSjeremylt   *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) &&
180a681ae63Sjeremylt                           (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
181a681ae63Sjeremylt                           (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
182e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1837a982d89SJeremy L. Thompson }
1847a982d89SJeremy L. Thompson 
1857a982d89SJeremy L. Thompson /**
18649fd234cSJeremy L Thompson 
18749fd234cSJeremy L Thompson   @brief Get the E-vector layout of a CeedElemRestriction
18849fd234cSJeremy L Thompson 
18949fd234cSJeremy L Thompson   @param rstr         CeedElemRestriction
19049fd234cSJeremy L Thompson   @param[out] layout  Variable to store layout array,
19149fd234cSJeremy L Thompson                         stored as [nodes, components, elements].
19249fd234cSJeremy L Thompson                         The data for node i, component j, element k in the
19349fd234cSJeremy L Thompson                         E-vector is given by
19495e93d34SJeremy L Thompson                         i*layout[0] + j*layout[1] + k*layout[2]
19549fd234cSJeremy L Thompson 
19649fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
19749fd234cSJeremy L Thompson 
19849fd234cSJeremy L Thompson   @ref Backend
19949fd234cSJeremy L Thompson **/
20049fd234cSJeremy L Thompson int CeedElemRestrictionGetELayout(CeedElemRestriction rstr,
20149fd234cSJeremy L Thompson                                   CeedInt (*layout)[3]) {
20249fd234cSJeremy L Thompson   if (!rstr->layout[0])
20349fd234cSJeremy L Thompson     // LCOV_EXCL_START
204e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_MINOR,
205e15f9bd0SJeremy L Thompson                      "ElemRestriction has no layout data");
20649fd234cSJeremy L Thompson   // LCOV_EXCL_STOP
20749fd234cSJeremy L Thompson 
20849fd234cSJeremy L Thompson   for (int i=0; i<3; i++)
20949fd234cSJeremy L Thompson     (*layout)[i] = rstr->layout[i];
210e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
21149fd234cSJeremy L Thompson }
21249fd234cSJeremy L Thompson 
21349fd234cSJeremy L Thompson /**
21449fd234cSJeremy L Thompson 
21549fd234cSJeremy L Thompson   @brief Set the E-vector layout of a CeedElemRestriction
21649fd234cSJeremy L Thompson 
21749fd234cSJeremy L Thompson   @param rstr    CeedElemRestriction
21849fd234cSJeremy L Thompson   @param layout  Variable to containing layout array,
21949fd234cSJeremy L Thompson                    stored as [nodes, components, elements].
22049fd234cSJeremy L Thompson                    The data for node i, component j, element k in the
22149fd234cSJeremy L Thompson                    E-vector is given by
22295e93d34SJeremy L Thompson                    i*layout[0] + j*layout[1] + k*layout[2]
22349fd234cSJeremy L Thompson 
22449fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
22549fd234cSJeremy L Thompson 
22649fd234cSJeremy L Thompson   @ref Backend
22749fd234cSJeremy L Thompson **/
22849fd234cSJeremy L Thompson int CeedElemRestrictionSetELayout(CeedElemRestriction rstr,
22949fd234cSJeremy L Thompson                                   CeedInt layout[3]) {
23049fd234cSJeremy L Thompson   for (int i = 0; i<3; i++)
23149fd234cSJeremy L Thompson     rstr->layout[i] = layout[i];
232e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
23349fd234cSJeremy L Thompson }
23449fd234cSJeremy L Thompson 
23549fd234cSJeremy L Thompson /**
2367a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedElemRestriction
2377a982d89SJeremy L. Thompson 
2387a982d89SJeremy L. Thompson   @param rstr       CeedElemRestriction
2397a982d89SJeremy L. Thompson   @param[out] data  Variable to store data
2407a982d89SJeremy L. Thompson 
2417a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2427a982d89SJeremy L. Thompson 
2437a982d89SJeremy L. Thompson   @ref Backend
2447a982d89SJeremy L. Thompson **/
245777ff853SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) {
246777ff853SJeremy L Thompson   *(void **)data = rstr->data;
247e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2487a982d89SJeremy L. Thompson }
2497a982d89SJeremy L. Thompson 
2507a982d89SJeremy L. Thompson /**
2517a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedElemRestriction
2527a982d89SJeremy L. Thompson 
2537a982d89SJeremy L. Thompson   @param[out] rstr  CeedElemRestriction
2547a982d89SJeremy L. Thompson   @param data       Data to set
2557a982d89SJeremy L. Thompson 
2567a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2577a982d89SJeremy L. Thompson 
2587a982d89SJeremy L. Thompson   @ref Backend
2597a982d89SJeremy L. Thompson **/
260777ff853SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) {
261777ff853SJeremy L Thompson   rstr->data = data;
262e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2637a982d89SJeremy L. Thompson }
2647a982d89SJeremy L. Thompson 
26534359f16Sjeremylt /**
26634359f16Sjeremylt   @brief Increment the reference counter for a CeedElemRestriction
26734359f16Sjeremylt 
26834359f16Sjeremylt   @param rstr  ElemRestriction to increment the reference counter
26934359f16Sjeremylt 
27034359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
27134359f16Sjeremylt 
27234359f16Sjeremylt   @ref Backend
27334359f16Sjeremylt **/
2749560d06aSjeremylt int CeedElemRestrictionReference(CeedElemRestriction rstr) {
27534359f16Sjeremylt   rstr->ref_count++;
27634359f16Sjeremylt   return CEED_ERROR_SUCCESS;
27734359f16Sjeremylt }
27834359f16Sjeremylt 
2796e15d496SJeremy L Thompson /**
2806e15d496SJeremy L Thompson   @brief Estimate number of FLOPs required to apply CeedElemRestriction in t_mode
2816e15d496SJeremy L Thompson 
2826e15d496SJeremy L Thompson   @param rstr   ElemRestriction to estimate FLOPs for
2836e15d496SJeremy L Thompson   @param t_mode Apply restriction or transpose
2846e15d496SJeremy L Thompson   @param flops  Address of variable to hold FLOPs estimate
2856e15d496SJeremy L Thompson 
2866e15d496SJeremy L Thompson   @ref Backend
2876e15d496SJeremy L Thompson **/
2886e15d496SJeremy L Thompson int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr,
289*9d36ca50SJeremy L Thompson                                         CeedTransposeMode t_mode, CeedSize *flops) {
2906e15d496SJeremy L Thompson   int ierr;
2916e15d496SJeremy L Thompson   bool is_oriented;
2926e15d496SJeremy L Thompson   CeedInt e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size *
2936e15d496SJeremy L Thompson                    rstr->num_comp,
2946e15d496SJeremy L Thompson                    scale = 0;
2956e15d496SJeremy L Thompson 
2966e15d496SJeremy L Thompson   ierr = CeedElemRestrictionIsOriented(rstr, &is_oriented); CeedChk(ierr);
2976e15d496SJeremy L Thompson   switch (t_mode) {
2986e15d496SJeremy L Thompson   case CEED_NOTRANSPOSE: scale = is_oriented ? 1 : 0; break;
2996e15d496SJeremy L Thompson   case CEED_TRANSPOSE:   scale = is_oriented ? 2 : 1; break;
3006e15d496SJeremy L Thompson   }
3016e15d496SJeremy L Thompson   *flops = e_size * scale;
3026e15d496SJeremy L Thompson 
3036e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3046e15d496SJeremy L Thompson }
3056e15d496SJeremy L Thompson 
3067a982d89SJeremy L. Thompson /// @}
3077a982d89SJeremy L. Thompson 
30815910d16Sjeremylt /// @cond DOXYGEN_SKIP
30915910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
31015910d16Sjeremylt /// @endcond
31115910d16Sjeremylt 
3127a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
3137a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
3147a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
3157a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
316d7b241e6Sjeremylt /// @{
317d7b241e6Sjeremylt 
3187a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
31945f1e315Sjeremylt const CeedInt CEED_STRIDES_BACKEND[3] = {0};
3207a982d89SJeremy L. Thompson 
3214cc79fe7SJed Brown /// Indicate that no CeedElemRestriction is provided by the user
3227a982d89SJeremy L. Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE =
3237a982d89SJeremy L. Thompson   &ceed_elemrestriction_none;
3247a982d89SJeremy L. Thompson 
325d7b241e6Sjeremylt /**
326b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
327d7b241e6Sjeremylt 
328b11c1e72Sjeremylt   @param ceed         A Ceed object where the CeedElemRestriction will be created
329d1d35e2fSjeremylt   @param num_elem     Number of elements described in the @a offsets array
330d1d35e2fSjeremylt   @param elem_size    Size (number of "nodes") per element
331d1d35e2fSjeremylt   @param num_comp     Number of field components per interpolation node
33295bb1877Svaleriabarra                         (1 for scalar fields)
333d1d35e2fSjeremylt   @param comp_stride  Stride between components for the same L-vector "node".
33495e93d34SJeremy L Thompson                         Data for node i, component j, element k can be found in
33595e93d34SJeremy L Thompson                         the L-vector at index
336d1d35e2fSjeremylt                         offsets[i + k*elem_size] + j*comp_stride.
337d1d35e2fSjeremylt   @param l_size       The size of the L-vector. This vector may be larger than
338d979a051Sjeremylt                         the elements and fields given by this restriction.
339d1d35e2fSjeremylt   @param mem_type     Memory type of the @a offsets array, see CeedMemType
340d1d35e2fSjeremylt   @param copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
341d1d35e2fSjeremylt   @param offsets      Array of shape [@a num_elem, @a elem_size]. Row i holds the
342d979a051Sjeremylt                         ordered list of the offsets (into the input CeedVector)
3438795c945Sjeremylt                         for the unknowns corresponding to element i, where
344d1d35e2fSjeremylt                         0 <= i < @a num_elem. All offsets must be in the range
345d1d35e2fSjeremylt                         [0, @a l_size - 1].
3464ce2993fSjeremylt   @param[out] rstr    Address of the variable where the newly created
347b11c1e72Sjeremylt                         CeedElemRestriction will be stored
348d7b241e6Sjeremylt 
349b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
350dfdf5a53Sjeremylt 
3517a982d89SJeremy L. Thompson   @ref User
352b11c1e72Sjeremylt **/
353d1d35e2fSjeremylt int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size,
354d1d35e2fSjeremylt                               CeedInt num_comp, CeedInt comp_stride,
355e79b91d9SJeremy L Thompson                               CeedSize l_size, CeedMemType mem_type,
356d1d35e2fSjeremylt                               CeedCopyMode copy_mode, const CeedInt *offsets,
3574ce2993fSjeremylt                               CeedElemRestriction *rstr) {
358d7b241e6Sjeremylt   int ierr;
359d7b241e6Sjeremylt 
3605fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
3615fe0d4faSjeremylt     Ceed delegate;
362aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
363aefd8378Sjeremylt     CeedChk(ierr);
3645fe0d4faSjeremylt 
3655fe0d4faSjeremylt     if (!delegate)
366c042f62fSJeremy L Thompson       // LCOV_EXCL_START
367e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
368e15f9bd0SJeremy L Thompson                        "Backend does not support ElemRestrictionCreate");
369c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
3705fe0d4faSjeremylt 
371d1d35e2fSjeremylt     ierr = CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp,
372d1d35e2fSjeremylt                                      comp_stride, l_size, mem_type, copy_mode,
373d979a051Sjeremylt                                      offsets, rstr); CeedChk(ierr);
374e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
3755fe0d4faSjeremylt   }
3765fe0d4faSjeremylt 
3774ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
3784ce2993fSjeremylt   (*rstr)->ceed = ceed;
3799560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
380d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
381d1d35e2fSjeremylt   (*rstr)->num_elem = num_elem;
382d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
383d1d35e2fSjeremylt   (*rstr)->num_comp = num_comp;
384d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
385d1d35e2fSjeremylt   (*rstr)->l_size = l_size;
386d1d35e2fSjeremylt   (*rstr)->num_blk = num_elem;
387d1d35e2fSjeremylt   (*rstr)->blk_size = 1;
388b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 0;
389d1d35e2fSjeremylt   ierr = ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, *rstr);
390d979a051Sjeremylt   CeedChk(ierr);
391e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
392d7b241e6Sjeremylt }
393d7b241e6Sjeremylt 
394d7b241e6Sjeremylt /**
395fc0567d9Srezgarshakeri   @brief Create a CeedElemRestriction with orientation sign
396fc0567d9Srezgarshakeri 
397fc0567d9Srezgarshakeri   @param ceed         A Ceed object where the CeedElemRestriction will be created
398fc0567d9Srezgarshakeri   @param num_elem     Number of elements described in the @a offsets array
399fc0567d9Srezgarshakeri   @param elem_size    Size (number of "nodes") per element
400fc0567d9Srezgarshakeri   @param num_comp     Number of field components per interpolation node
401fc0567d9Srezgarshakeri                         (1 for scalar fields)
402fc0567d9Srezgarshakeri   @param comp_stride  Stride between components for the same L-vector "node".
403fc0567d9Srezgarshakeri                         Data for node i, component j, element k can be found in
404fc0567d9Srezgarshakeri                         the L-vector at index
405fc0567d9Srezgarshakeri                         offsets[i + k*elem_size] + j*comp_stride.
406fc0567d9Srezgarshakeri   @param l_size       The size of the L-vector. This vector may be larger than
407fc0567d9Srezgarshakeri                         the elements and fields given by this restriction.
408fc0567d9Srezgarshakeri   @param mem_type     Memory type of the @a offsets array, see CeedMemType
409fc0567d9Srezgarshakeri   @param copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
410fc0567d9Srezgarshakeri   @param offsets      Array of shape [@a num_elem, @a elem_size]. Row i holds the
411fc0567d9Srezgarshakeri                         ordered list of the offsets (into the input CeedVector)
412fc0567d9Srezgarshakeri                         for the unknowns corresponding to element i, where
413fc0567d9Srezgarshakeri                         0 <= i < @a num_elem. All offsets must be in the range
414fc0567d9Srezgarshakeri                         [0, @a l_size - 1].
415fc0567d9Srezgarshakeri   @param orient       Array of shape [@a num_elem, @a elem_size] with bool false
416fc0567d9Srezgarshakeri                         for positively oriented and true to flip the orientation.
417fc0567d9Srezgarshakeri   @param[out] rstr    Address of the variable where the newly created
418fc0567d9Srezgarshakeri                         CeedElemRestriction will be stored
419fc0567d9Srezgarshakeri 
420fc0567d9Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
421fc0567d9Srezgarshakeri 
422fc0567d9Srezgarshakeri   @ref User
423fc0567d9Srezgarshakeri **/
424fc0567d9Srezgarshakeri int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem,
425fc0567d9Srezgarshakeri                                       CeedInt elem_size, CeedInt num_comp,
426e79b91d9SJeremy L Thompson                                       CeedInt comp_stride, CeedSize l_size,
427fc0567d9Srezgarshakeri                                       CeedMemType mem_type, CeedCopyMode copy_mode,
428fc0567d9Srezgarshakeri                                       const CeedInt *offsets, const bool *orient,
429fc0567d9Srezgarshakeri                                       CeedElemRestriction *rstr) {
430fc0567d9Srezgarshakeri   int ierr;
431fc0567d9Srezgarshakeri 
432c7745053SRezgar Shakeri   if (!ceed->ElemRestrictionCreateOriented) {
433fc0567d9Srezgarshakeri     Ceed delegate;
434fc0567d9Srezgarshakeri     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
435fc0567d9Srezgarshakeri     CeedChk(ierr);
436fc0567d9Srezgarshakeri 
437fc0567d9Srezgarshakeri     if (!delegate)
438fc0567d9Srezgarshakeri       // LCOV_EXCL_START
439fc0567d9Srezgarshakeri       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
44061e7462cSRezgar Shakeri                        "Backend does not implement ElemRestrictionCreateOriented");
441fc0567d9Srezgarshakeri     // LCOV_EXCL_STOP
442fc0567d9Srezgarshakeri 
443fc0567d9Srezgarshakeri     ierr = CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size,
444c7745053SRezgar Shakeri            num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
4454dd06d33Srezgarshakeri            orient, rstr); CeedChk(ierr);
446fc0567d9Srezgarshakeri     return CEED_ERROR_SUCCESS;
447fc0567d9Srezgarshakeri   }
448fc0567d9Srezgarshakeri 
449fc0567d9Srezgarshakeri   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
450fc0567d9Srezgarshakeri   (*rstr)->ceed = ceed;
451fc0567d9Srezgarshakeri   ierr = CeedReference(ceed); CeedChk(ierr);
452fc0567d9Srezgarshakeri   (*rstr)->ref_count = 1;
453fc0567d9Srezgarshakeri   (*rstr)->num_elem = num_elem;
454fc0567d9Srezgarshakeri   (*rstr)->elem_size = elem_size;
455fc0567d9Srezgarshakeri   (*rstr)->num_comp = num_comp;
456fc0567d9Srezgarshakeri   (*rstr)->comp_stride = comp_stride;
457fc0567d9Srezgarshakeri   (*rstr)->l_size = l_size;
458fc0567d9Srezgarshakeri   (*rstr)->num_blk = num_elem;
459fc0567d9Srezgarshakeri   (*rstr)->blk_size = 1;
460b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 1;
4614dd06d33Srezgarshakeri   ierr = ceed->ElemRestrictionCreateOriented(mem_type, copy_mode,
4624dd06d33Srezgarshakeri          offsets, orient, *rstr); CeedChk(ierr);
463fc0567d9Srezgarshakeri   return CEED_ERROR_SUCCESS;
464fc0567d9Srezgarshakeri }
465fc0567d9Srezgarshakeri 
466fc0567d9Srezgarshakeri /**
4677509a596Sjeremylt   @brief Create a strided CeedElemRestriction
468d7b241e6Sjeremylt 
469b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
470d1d35e2fSjeremylt   @param num_elem   Number of elements described by the restriction
471d1d35e2fSjeremylt   @param elem_size  Size (number of "nodes") per element
472d1d35e2fSjeremylt   @param num_comp   Number of field components per interpolation "node"
47395bb1877Svaleriabarra                       (1 for scalar fields)
474d1d35e2fSjeremylt   @param l_size     The size of the L-vector. This vector may be larger than
475d979a051Sjeremylt                       the elements and fields given by this restriction.
4767509a596Sjeremylt   @param strides    Array for strides between [nodes, components, elements].
47795e93d34SJeremy L Thompson                       Data for node i, component j, element k can be found in
47895e93d34SJeremy L Thompson                       the L-vector at index
47995e93d34SJeremy L Thompson                       i*strides[0] + j*strides[1] + k*strides[2].
48095e93d34SJeremy L Thompson                       @a CEED_STRIDES_BACKEND may be used with vectors created
48195e93d34SJeremy L Thompson                       by a Ceed backend.
4824ce2993fSjeremylt   @param rstr       Address of the variable where the newly created
483b11c1e72Sjeremylt                       CeedElemRestriction will be stored
484d7b241e6Sjeremylt 
485b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
486dfdf5a53Sjeremylt 
4877a982d89SJeremy L. Thompson   @ref User
488b11c1e72Sjeremylt **/
489d1d35e2fSjeremylt int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem,
490d1d35e2fSjeremylt                                      CeedInt elem_size,
491e79b91d9SJeremy L Thompson                                      CeedInt num_comp, CeedSize l_size,
4928621c6c6SJeremy L Thompson                                      const CeedInt strides[3],
493f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
494d7b241e6Sjeremylt   int ierr;
495d7b241e6Sjeremylt 
4965fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
4975fe0d4faSjeremylt     Ceed delegate;
498aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
499aefd8378Sjeremylt     CeedChk(ierr);
5005fe0d4faSjeremylt 
5015fe0d4faSjeremylt     if (!delegate)
502c042f62fSJeremy L Thompson       // LCOV_EXCL_START
503e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
504e15f9bd0SJeremy L Thompson                        "Backend does not support ElemRestrictionCreate");
505c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
5065fe0d4faSjeremylt 
507d1d35e2fSjeremylt     ierr = CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp,
508d1d35e2fSjeremylt                                             l_size, strides, rstr);
509d979a051Sjeremylt     CeedChk(ierr);
510e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
5115fe0d4faSjeremylt   }
5125fe0d4faSjeremylt 
5134ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
5144ce2993fSjeremylt   (*rstr)->ceed = ceed;
5159560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
516d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
517d1d35e2fSjeremylt   (*rstr)->num_elem = num_elem;
518d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
519d1d35e2fSjeremylt   (*rstr)->num_comp = num_comp;
520d1d35e2fSjeremylt   (*rstr)->l_size = l_size;
521d1d35e2fSjeremylt   (*rstr)->num_blk = num_elem;
522d1d35e2fSjeremylt   (*rstr)->blk_size = 1;
523b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 0;
5247509a596Sjeremylt   ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr);
5257509a596Sjeremylt   for (int i=0; i<3; i++)
5267509a596Sjeremylt     (*rstr)->strides[i] = strides[i];
5271dfeef1dSjeremylt   ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL,
5281dfeef1dSjeremylt                                      *rstr);
5294b8bea3bSJed Brown   CeedChk(ierr);
530e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
531d7b241e6Sjeremylt }
532d7b241e6Sjeremylt 
533d7b241e6Sjeremylt /**
534b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
535d7b241e6Sjeremylt 
536d7b241e6Sjeremylt   @param ceed         A Ceed object where the CeedElemRestriction will be created.
537d1d35e2fSjeremylt   @param num_elem     Number of elements described in the @a offsets array.
538d1d35e2fSjeremylt   @param elem_size    Size (number of unknowns) per element
539d1d35e2fSjeremylt   @param blk_size     Number of elements in a block
540d1d35e2fSjeremylt   @param num_comp     Number of field components per interpolation node
54195bb1877Svaleriabarra                         (1 for scalar fields)
542d1d35e2fSjeremylt   @param comp_stride  Stride between components for the same L-vector "node".
54395e93d34SJeremy L Thompson                         Data for node i, component j, element k can be found in
54495e93d34SJeremy L Thompson                         the L-vector at index
545d1d35e2fSjeremylt                         offsets[i + k*elem_size] + j*comp_stride.
546d1d35e2fSjeremylt   @param l_size       The size of the L-vector. This vector may be larger than
547d979a051Sjeremylt                         the elements and fields given by this restriction.
548d1d35e2fSjeremylt   @param mem_type     Memory type of the @a offsets array, see CeedMemType
549d1d35e2fSjeremylt   @param copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
550d1d35e2fSjeremylt   @param offsets      Array of shape [@a num_elem, @a elem_size]. Row i holds the
551d979a051Sjeremylt                         ordered list of the offsets (into the input CeedVector)
5528795c945Sjeremylt                         for the unknowns corresponding to element i, where
553d1d35e2fSjeremylt                         0 <= i < @a num_elem. All offsets must be in the range
554d1d35e2fSjeremylt                         [0, @a l_size - 1]. The backend will permute and pad this
5558795c945Sjeremylt                         array to the desired ordering for the blocksize, which is
5568795c945Sjeremylt                         typically given by the backend. The default reordering is
5578795c945Sjeremylt                         to interlace elements.
5584ce2993fSjeremylt   @param rstr         Address of the variable where the newly created
559b11c1e72Sjeremylt                         CeedElemRestriction will be stored
560d7b241e6Sjeremylt 
561b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
562dfdf5a53Sjeremylt 
5637a982d89SJeremy L. Thompson   @ref Backend
564b11c1e72Sjeremylt  **/
565d1d35e2fSjeremylt int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem,
566d1d35e2fSjeremylt                                      CeedInt elem_size,
567d1d35e2fSjeremylt                                      CeedInt blk_size, CeedInt num_comp,
568e79b91d9SJeremy L Thompson                                      CeedInt comp_stride, CeedSize l_size,
569d1d35e2fSjeremylt                                      CeedMemType mem_type, CeedCopyMode copy_mode,
570d979a051Sjeremylt                                      const CeedInt *offsets,
5714ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
572d7b241e6Sjeremylt   int ierr;
573d1d35e2fSjeremylt   CeedInt *blk_offsets;
574d1d35e2fSjeremylt   CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
575d7b241e6Sjeremylt 
5765fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
5775fe0d4faSjeremylt     Ceed delegate;
578aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
579aefd8378Sjeremylt     CeedChk(ierr);
5805fe0d4faSjeremylt 
5815fe0d4faSjeremylt     if (!delegate)
582c042f62fSJeremy L Thompson       // LCOV_EXCL_START
583e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support "
5841d102b48SJeremy L Thompson                        "ElemRestrictionCreateBlocked");
585c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
5865fe0d4faSjeremylt 
587d1d35e2fSjeremylt     ierr = CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, blk_size,
588d1d35e2fSjeremylt                                             num_comp, comp_stride, l_size, mem_type,
589d1d35e2fSjeremylt                                             copy_mode, offsets, rstr);
590d979a051Sjeremylt     CeedChk(ierr);
591e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
5925fe0d4faSjeremylt   }
593d7b241e6Sjeremylt 
5944ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
595d7b241e6Sjeremylt 
596d1d35e2fSjeremylt   ierr = CeedCalloc(num_blk*blk_size*elem_size, &blk_offsets); CeedChk(ierr);
597d1d35e2fSjeremylt   ierr = CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size,
598d1d35e2fSjeremylt                                elem_size); CeedChk(ierr);
599d7b241e6Sjeremylt 
6004ce2993fSjeremylt   (*rstr)->ceed = ceed;
6019560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
602d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
603d1d35e2fSjeremylt   (*rstr)->num_elem = num_elem;
604d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
605d1d35e2fSjeremylt   (*rstr)->num_comp = num_comp;
606d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
607d1d35e2fSjeremylt   (*rstr)->l_size = l_size;
608d1d35e2fSjeremylt   (*rstr)->num_blk = num_blk;
609d1d35e2fSjeremylt   (*rstr)->blk_size = blk_size;
610b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 0;
611667bc5fcSjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
612d1d35e2fSjeremylt          (const CeedInt *) blk_offsets, *rstr); CeedChk(ierr);
613d1d35e2fSjeremylt   if (copy_mode == CEED_OWN_POINTER) {
614d979a051Sjeremylt     ierr = CeedFree(&offsets); CeedChk(ierr);
6151d102b48SJeremy L Thompson   }
616e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
617d7b241e6Sjeremylt }
618d7b241e6Sjeremylt 
619b11c1e72Sjeremylt /**
6207509a596Sjeremylt   @brief Create a blocked strided CeedElemRestriction
6217509a596Sjeremylt 
6227509a596Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
623d1d35e2fSjeremylt   @param num_elem   Number of elements described by the restriction
624d1d35e2fSjeremylt   @param elem_size  Size (number of "nodes") per element
625d1d35e2fSjeremylt   @param blk_size   Number of elements in a block
626d1d35e2fSjeremylt   @param num_comp   Number of field components per interpolation node
6277509a596Sjeremylt                       (1 for scalar fields)
628d1d35e2fSjeremylt   @param l_size     The size of the L-vector. This vector may be larger than
629d979a051Sjeremylt                       the elements and fields given by this restriction.
6307509a596Sjeremylt   @param strides    Array for strides between [nodes, components, elements].
63195e93d34SJeremy L Thompson                       Data for node i, component j, element k can be found in
63295e93d34SJeremy L Thompson                       the L-vector at index
63395e93d34SJeremy L Thompson                       i*strides[0] + j*strides[1] + k*strides[2].
63495e93d34SJeremy L Thompson                       @a CEED_STRIDES_BACKEND may be used with vectors created
63595e93d34SJeremy L Thompson                       by a Ceed backend.
6367509a596Sjeremylt   @param rstr       Address of the variable where the newly created
6377509a596Sjeremylt                       CeedElemRestriction will be stored
6387509a596Sjeremylt 
6397509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
6407509a596Sjeremylt 
6417a982d89SJeremy L. Thompson   @ref User
6427509a596Sjeremylt **/
643d1d35e2fSjeremylt int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem,
644e79b91d9SJeremy L Thompson     CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedSize l_size,
6458621c6c6SJeremy L Thompson     const CeedInt strides[3], CeedElemRestriction *rstr) {
6467509a596Sjeremylt   int ierr;
647d1d35e2fSjeremylt   CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
6487509a596Sjeremylt 
6497509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
6507509a596Sjeremylt     Ceed delegate;
6517509a596Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
6527509a596Sjeremylt     CeedChk(ierr);
6537509a596Sjeremylt 
6547509a596Sjeremylt     if (!delegate)
6557509a596Sjeremylt       // LCOV_EXCL_START
656e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support "
6577509a596Sjeremylt                        "ElemRestrictionCreateBlocked");
6587509a596Sjeremylt     // LCOV_EXCL_STOP
6597509a596Sjeremylt 
660d1d35e2fSjeremylt     ierr = CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size,
661d1d35e2fSjeremylt            blk_size, num_comp, l_size, strides, rstr); CeedChk(ierr);
662e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6637509a596Sjeremylt   }
6647509a596Sjeremylt 
6657509a596Sjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
6667509a596Sjeremylt 
6677509a596Sjeremylt   (*rstr)->ceed = ceed;
6689560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
669d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
670d1d35e2fSjeremylt   (*rstr)->num_elem = num_elem;
671d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
672d1d35e2fSjeremylt   (*rstr)->num_comp = num_comp;
673d1d35e2fSjeremylt   (*rstr)->l_size = l_size;
674d1d35e2fSjeremylt   (*rstr)->num_blk = num_blk;
675d1d35e2fSjeremylt   (*rstr)->blk_size = blk_size;
676b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 0;
6777509a596Sjeremylt   ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr);
6787509a596Sjeremylt   for (int i=0; i<3; i++)
6797509a596Sjeremylt     (*rstr)->strides[i] = strides[i];
6807509a596Sjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
6817509a596Sjeremylt          NULL, *rstr); CeedChk(ierr);
682e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6837509a596Sjeremylt }
6847509a596Sjeremylt 
6857509a596Sjeremylt /**
6869560d06aSjeremylt   @brief Copy the pointer to a CeedElemRestriction. Both pointers should
6879560d06aSjeremylt            be destroyed with `CeedElemRestrictionDestroy()`;
6889560d06aSjeremylt            Note: If `*rstr_copy` is non-NULL, then it is assumed that
6899560d06aSjeremylt            `*rstr_copy` is a pointer to a CeedElemRestriction. This
6909560d06aSjeremylt            CeedElemRestriction will be destroyed if `*rstr_copy` is the
6919560d06aSjeremylt            only reference to this CeedElemRestriction.
6929560d06aSjeremylt 
6939560d06aSjeremylt   @param rstr            CeedElemRestriction to copy reference to
6949560d06aSjeremylt   @param[out] rstr_copy  Variable to store copied reference
6959560d06aSjeremylt 
6969560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
6979560d06aSjeremylt 
6989560d06aSjeremylt   @ref User
6999560d06aSjeremylt **/
7009560d06aSjeremylt int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr,
7019560d06aSjeremylt                                      CeedElemRestriction *rstr_copy) {
7029560d06aSjeremylt   int ierr;
7039560d06aSjeremylt 
7049560d06aSjeremylt   ierr = CeedElemRestrictionReference(rstr); CeedChk(ierr);
7059560d06aSjeremylt   ierr = CeedElemRestrictionDestroy(rstr_copy); CeedChk(ierr);
7069560d06aSjeremylt   *rstr_copy = rstr;
7079560d06aSjeremylt   return CEED_ERROR_SUCCESS;
7089560d06aSjeremylt }
7099560d06aSjeremylt 
7109560d06aSjeremylt /**
711b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
712b11c1e72Sjeremylt 
7134ce2993fSjeremylt   @param rstr   CeedElemRestriction
714d1d35e2fSjeremylt   @param l_vec  The address of the L-vector to be created, or NULL
715d1d35e2fSjeremylt   @param e_vec  The address of the E-vector to be created, or NULL
716b11c1e72Sjeremylt 
717b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
718dfdf5a53Sjeremylt 
7197a982d89SJeremy L. Thompson   @ref User
720b11c1e72Sjeremylt **/
721d1d35e2fSjeremylt int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec,
722d1d35e2fSjeremylt                                     CeedVector *e_vec) {
723d7b241e6Sjeremylt   int ierr;
724d2643443SJeremy L Thompson   CeedSize e_size, l_size;
725d1d35e2fSjeremylt   l_size = rstr->l_size;
726d1d35e2fSjeremylt   e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
727d1d35e2fSjeremylt   if (l_vec) {
728d1d35e2fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, l_size, l_vec); CeedChk(ierr);
729d7b241e6Sjeremylt   }
730d1d35e2fSjeremylt   if (e_vec) {
731d1d35e2fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, e_size, e_vec); CeedChk(ierr);
732d7b241e6Sjeremylt   }
733e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
734d7b241e6Sjeremylt }
735d7b241e6Sjeremylt 
736d7b241e6Sjeremylt /**
737d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
738d7b241e6Sjeremylt 
7394ce2993fSjeremylt   @param rstr    CeedElemRestriction
740d1d35e2fSjeremylt   @param t_mode  Apply restriction or transpose
741d1d35e2fSjeremylt   @param u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
742d1d35e2fSjeremylt   @param ru      Output vector (of shape [@a num_elem * @a elem_size] when
743d1d35e2fSjeremylt                    t_mode=@ref CEED_NOTRANSPOSE). Ordering of the e-vector is decided
7447aaeacdcSjeremylt                    by the backend.
7454cc79fe7SJed Brown   @param request Request or @ref CEED_REQUEST_IMMEDIATE
746b11c1e72Sjeremylt 
747b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
748dfdf5a53Sjeremylt 
7497a982d89SJeremy L. Thompson   @ref User
750b11c1e72Sjeremylt **/
751d1d35e2fSjeremylt int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode,
752a8d32208Sjeremylt                              CeedVector u, CeedVector ru,
753a8d32208Sjeremylt                              CeedRequest *request) {
754d7b241e6Sjeremylt   CeedInt m, n;
755d7b241e6Sjeremylt   int ierr;
756d7b241e6Sjeremylt 
757d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
758d1d35e2fSjeremylt     m = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
759d1d35e2fSjeremylt     n = rstr->l_size;
760d7b241e6Sjeremylt   } else {
761d1d35e2fSjeremylt     m = rstr->l_size;
762d1d35e2fSjeremylt     n = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
763d7b241e6Sjeremylt   }
764d7b241e6Sjeremylt   if (n != u->length)
765c042f62fSJeremy L Thompson     // LCOV_EXCL_START
766e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
767e15f9bd0SJeremy L Thompson                      "Input vector size %d not compatible with "
7681d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
769c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
770a8d32208Sjeremylt   if (m != ru->length)
771c042f62fSJeremy L Thompson     // LCOV_EXCL_START
772e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
773e15f9bd0SJeremy L Thompson                      "Output vector size %d not compatible with "
774a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
775c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
776d1d35e2fSjeremylt   ierr = rstr->Apply(rstr, t_mode, u, ru, request); CeedChk(ierr);
777e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
778d7b241e6Sjeremylt }
779d7b241e6Sjeremylt 
780d7b241e6Sjeremylt /**
781d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
782be9261b7Sjeremylt 
783be9261b7Sjeremylt   @param rstr    CeedElemRestriction
7841f37b403Sjeremylt   @param block   Block number to restrict to/from, i.e. block=0 will handle
785d1d35e2fSjeremylt                    elements [0 : blk_size] and block=3 will handle elements
786d1d35e2fSjeremylt                    [3*blk_size : 4*blk_size]
787d1d35e2fSjeremylt   @param t_mode  Apply restriction or transpose
788d1d35e2fSjeremylt   @param u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
789d1d35e2fSjeremylt   @param ru      Output vector (of shape [@a blk_size * @a elem_size] when
790d1d35e2fSjeremylt                    t_mode=@ref CEED_NOTRANSPOSE). Ordering of the e-vector is decided
7917aaeacdcSjeremylt                    by the backend.
7924cc79fe7SJed Brown   @param request Request or @ref CEED_REQUEST_IMMEDIATE
793be9261b7Sjeremylt 
794be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
795be9261b7Sjeremylt 
7967a982d89SJeremy L. Thompson   @ref Backend
797be9261b7Sjeremylt **/
798be9261b7Sjeremylt int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block,
799d1d35e2fSjeremylt                                   CeedTransposeMode t_mode, CeedVector u,
800a8d32208Sjeremylt                                   CeedVector ru, CeedRequest *request) {
801be9261b7Sjeremylt   CeedInt m, n;
802be9261b7Sjeremylt   int ierr;
803be9261b7Sjeremylt 
804d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
805d1d35e2fSjeremylt     m = rstr->blk_size * rstr->elem_size * rstr->num_comp;
806d1d35e2fSjeremylt     n = rstr->l_size;
807be9261b7Sjeremylt   } else {
808d1d35e2fSjeremylt     m = rstr->l_size;
809d1d35e2fSjeremylt     n = rstr->blk_size * rstr->elem_size * rstr->num_comp;
810be9261b7Sjeremylt   }
811be9261b7Sjeremylt   if (n != u->length)
812c042f62fSJeremy L Thompson     // LCOV_EXCL_START
813e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
814e15f9bd0SJeremy L Thompson                      "Input vector size %d not compatible with "
8151d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
816c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
817a8d32208Sjeremylt   if (m != ru->length)
818c042f62fSJeremy L Thompson     // LCOV_EXCL_START
819e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
820e15f9bd0SJeremy L Thompson                      "Output vector size %d not compatible with "
821a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
822c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
823d1d35e2fSjeremylt   if (rstr->blk_size*block > rstr->num_elem)
824c042f62fSJeremy L Thompson     // LCOV_EXCL_START
825e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
826e15f9bd0SJeremy L Thompson                      "Cannot retrieve block %d, element %d > "
827d1d35e2fSjeremylt                      "total elements %d", block, rstr->blk_size*block,
828d1d35e2fSjeremylt                      rstr->num_elem);
829c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
830d1d35e2fSjeremylt   ierr = rstr->ApplyBlock(rstr, block, t_mode, u, ru, request);
831be9261b7Sjeremylt   CeedChk(ierr);
832e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
833be9261b7Sjeremylt }
834be9261b7Sjeremylt 
835be9261b7Sjeremylt /**
836b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedElemRestriction
837b7c9bbdaSJeremy L Thompson 
838b7c9bbdaSJeremy L Thompson   @param rstr       CeedElemRestriction
839b7c9bbdaSJeremy L Thompson   @param[out] ceed  Variable to store Ceed
840b7c9bbdaSJeremy L Thompson 
841b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
842b7c9bbdaSJeremy L Thompson 
843b7c9bbdaSJeremy L Thompson   @ref Advanced
844b7c9bbdaSJeremy L Thompson **/
845b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
846b7c9bbdaSJeremy L Thompson   *ceed = rstr->ceed;
847b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
848b7c9bbdaSJeremy L Thompson }
849b7c9bbdaSJeremy L Thompson 
850b7c9bbdaSJeremy L Thompson /**
851d979a051Sjeremylt   @brief Get the L-vector component stride
852a681ae63Sjeremylt 
853a681ae63Sjeremylt   @param rstr              CeedElemRestriction
854d1d35e2fSjeremylt   @param[out] comp_stride  Variable to store component stride
855a681ae63Sjeremylt 
856a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
857a681ae63Sjeremylt 
858b7c9bbdaSJeremy L Thompson   @ref Advanced
859a681ae63Sjeremylt **/
860d979a051Sjeremylt int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr,
861d1d35e2fSjeremylt                                      CeedInt *comp_stride) {
862d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
863e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
864a681ae63Sjeremylt }
865a681ae63Sjeremylt 
866a681ae63Sjeremylt /**
867a681ae63Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
868a681ae63Sjeremylt 
869a681ae63Sjeremylt   @param rstr           CeedElemRestriction
870d1d35e2fSjeremylt   @param[out] num_elem  Variable to store number of elements
871a681ae63Sjeremylt 
872a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
873a681ae63Sjeremylt 
874b7c9bbdaSJeremy L Thompson   @ref Advanced
875a681ae63Sjeremylt **/
876a681ae63Sjeremylt int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
877d1d35e2fSjeremylt                                       CeedInt *num_elem) {
878d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
879e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
880a681ae63Sjeremylt }
881a681ae63Sjeremylt 
882a681ae63Sjeremylt /**
883a681ae63Sjeremylt   @brief Get the size of elements in the CeedElemRestriction
884a681ae63Sjeremylt 
885a681ae63Sjeremylt   @param rstr            CeedElemRestriction
886d1d35e2fSjeremylt   @param[out] elem_size  Variable to store size of elements
887a681ae63Sjeremylt 
888a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
889a681ae63Sjeremylt 
890b7c9bbdaSJeremy L Thompson   @ref Advanced
891a681ae63Sjeremylt **/
892a681ae63Sjeremylt int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
893d1d35e2fSjeremylt                                       CeedInt *elem_size) {
894d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
895e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
896a681ae63Sjeremylt }
897a681ae63Sjeremylt 
898a681ae63Sjeremylt /**
899d979a051Sjeremylt   @brief Get the size of the l-vector for a CeedElemRestriction
900a681ae63Sjeremylt 
901a681ae63Sjeremylt   @param rstr         CeedElemRestriction
902d1d35e2fSjeremylt   @param[out] l_size  Variable to store number of nodes
903a681ae63Sjeremylt 
904a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
905a681ae63Sjeremylt 
906b7c9bbdaSJeremy L Thompson   @ref Advanced
907a681ae63Sjeremylt **/
908d979a051Sjeremylt int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr,
909e79b91d9SJeremy L Thompson                                       CeedSize *l_size) {
910d1d35e2fSjeremylt   *l_size = rstr->l_size;
911e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
912a681ae63Sjeremylt }
913a681ae63Sjeremylt 
914a681ae63Sjeremylt /**
915a681ae63Sjeremylt   @brief Get the number of components in the elements of a
916a681ae63Sjeremylt          CeedElemRestriction
917a681ae63Sjeremylt 
918a681ae63Sjeremylt   @param rstr           CeedElemRestriction
919d1d35e2fSjeremylt   @param[out] num_comp  Variable to store number of components
920a681ae63Sjeremylt 
921a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
922a681ae63Sjeremylt 
923b7c9bbdaSJeremy L Thompson   @ref Advanced
924a681ae63Sjeremylt **/
925a681ae63Sjeremylt int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
926d1d35e2fSjeremylt                                         CeedInt *num_comp) {
927d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
928e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
929a681ae63Sjeremylt }
930a681ae63Sjeremylt 
931a681ae63Sjeremylt /**
932a681ae63Sjeremylt   @brief Get the number of blocks in a CeedElemRestriction
933a681ae63Sjeremylt 
934a681ae63Sjeremylt   @param rstr            CeedElemRestriction
935d1d35e2fSjeremylt   @param[out] num_block  Variable to store number of blocks
936a681ae63Sjeremylt 
937a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
938a681ae63Sjeremylt 
939b7c9bbdaSJeremy L Thompson   @ref Advanced
940a681ae63Sjeremylt **/
941a681ae63Sjeremylt int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
942d1d35e2fSjeremylt                                     CeedInt *num_block) {
943d1d35e2fSjeremylt   *num_block = rstr->num_blk;
944e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
945a681ae63Sjeremylt }
946a681ae63Sjeremylt 
947a681ae63Sjeremylt /**
948a681ae63Sjeremylt   @brief Get the size of blocks in the CeedElemRestriction
949a681ae63Sjeremylt 
950a681ae63Sjeremylt   @param rstr           CeedElemRestriction
951d1d35e2fSjeremylt   @param[out] blk_size  Variable to store size of blocks
952a681ae63Sjeremylt 
953a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
954a681ae63Sjeremylt 
955b7c9bbdaSJeremy L Thompson   @ref Advanced
956a681ae63Sjeremylt **/
957a681ae63Sjeremylt int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
958d1d35e2fSjeremylt                                     CeedInt *blk_size) {
959d1d35e2fSjeremylt   *blk_size = rstr->blk_size;
960e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
961a681ae63Sjeremylt }
962a681ae63Sjeremylt 
963a681ae63Sjeremylt /**
964d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
9651469ee4dSjeremylt 
9661469ee4dSjeremylt   @param rstr       CeedElemRestriction
967d1d35e2fSjeremylt   @param[out] mult  Vector to store multiplicity (of size l_size)
9681469ee4dSjeremylt 
9691469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
9701469ee4dSjeremylt 
9717a982d89SJeremy L. Thompson   @ref User
9721469ee4dSjeremylt **/
9731469ee4dSjeremylt int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr,
9741469ee4dSjeremylt                                        CeedVector mult) {
9751469ee4dSjeremylt   int ierr;
976d1d35e2fSjeremylt   CeedVector e_vec;
9771469ee4dSjeremylt 
97825509ebbSRezgar Shakeri   // Create e_vec to hold intermediate computation in E^T (E 1)
979d1d35e2fSjeremylt   ierr = CeedElemRestrictionCreateVector(rstr, NULL, &e_vec); CeedChk(ierr);
9801469ee4dSjeremylt 
98125509ebbSRezgar Shakeri   // Compute e_vec = E * 1
98225509ebbSRezgar Shakeri   ierr = CeedVectorSetValue(mult, 1.0); CeedChk(ierr);
98325509ebbSRezgar Shakeri   ierr = CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec,
98425509ebbSRezgar Shakeri                                   CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
98525509ebbSRezgar Shakeri   // Compute multiplicity, mult = E^T * e_vec = E^T (E 1)
98625509ebbSRezgar Shakeri   ierr = CeedVectorSetValue(mult, 0.0); CeedChk(ierr);
987d1d35e2fSjeremylt   ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult,
988efc78312Sjeremylt                                   CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
9891469ee4dSjeremylt   // Cleanup
990d1d35e2fSjeremylt   ierr = CeedVectorDestroy(&e_vec); CeedChk(ierr);
991e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
9921469ee4dSjeremylt }
9931469ee4dSjeremylt 
9941469ee4dSjeremylt /**
995f02ca4a2SJed Brown   @brief View a CeedElemRestriction
996f02ca4a2SJed Brown 
997f02ca4a2SJed Brown   @param[in] rstr    CeedElemRestriction to view
998f02ca4a2SJed Brown   @param[in] stream  Stream to write; typically stdout/stderr or a file
999f02ca4a2SJed Brown 
1000f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
1001f02ca4a2SJed Brown 
10027a982d89SJeremy L. Thompson   @ref User
1003f02ca4a2SJed Brown **/
1004f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
10057509a596Sjeremylt   char stridesstr[500];
10067509a596Sjeremylt   if (rstr->strides)
10077509a596Sjeremylt     sprintf(stridesstr, "[%d, %d, %d]", rstr->strides[0], rstr->strides[1],
10087509a596Sjeremylt             rstr->strides[2]);
1009d979a051Sjeremylt   else
1010d1d35e2fSjeremylt     sprintf(stridesstr, "%d", rstr->comp_stride);
10117509a596Sjeremylt 
10125b76854bSJeremy L Thompson   fprintf(stream, "%sCeedElemRestriction from (%td, %d) to %d elements with %d "
1013d1d35e2fSjeremylt           "nodes each and %s %s\n", rstr->blk_size > 1 ? "Blocked " : "",
1014d1d35e2fSjeremylt           rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
1015d979a051Sjeremylt           rstr->strides ? "strides" : "component stride", stridesstr);
1016e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1017f02ca4a2SJed Brown }
1018f02ca4a2SJed Brown 
1019f02ca4a2SJed Brown /**
1020b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
1021b11c1e72Sjeremylt 
10224ce2993fSjeremylt   @param rstr  CeedElemRestriction to destroy
1023b11c1e72Sjeremylt 
1024b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1025dfdf5a53Sjeremylt 
10267a982d89SJeremy L. Thompson   @ref User
1027b11c1e72Sjeremylt **/
10284ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
1029d7b241e6Sjeremylt   int ierr;
1030d7b241e6Sjeremylt 
1031d1d35e2fSjeremylt   if (!*rstr || --(*rstr)->ref_count > 0) return CEED_ERROR_SUCCESS;
1032d1d35e2fSjeremylt   if ((*rstr)->num_readers)
10338229195eSjeremylt     // LCOV_EXCL_START
1034e15f9bd0SJeremy L Thompson     return CeedError((*rstr)->ceed, CEED_ERROR_ACCESS,
1035e15f9bd0SJeremy L Thompson                      "Cannot destroy CeedElemRestriction, "
1036430758c8SJeremy L Thompson                      "a process has read access to the offset data");
10378229195eSjeremylt   // LCOV_EXCL_STOP
10384ce2993fSjeremylt   if ((*rstr)->Destroy) {
10394ce2993fSjeremylt     ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr);
1040d7b241e6Sjeremylt   }
10417509a596Sjeremylt   ierr = CeedFree(&(*rstr)->strides); CeedChk(ierr);
10424ce2993fSjeremylt   ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr);
10434ce2993fSjeremylt   ierr = CeedFree(rstr); CeedChk(ierr);
1044e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1045d7b241e6Sjeremylt }
1046d7b241e6Sjeremylt 
1047d7b241e6Sjeremylt /// @}
1048