xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-elemrestriction.c (revision 3d8e882215d238700cdceb37404f76ca7fa24eaa)
1*3d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
2*3d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3d7b241e6Sjeremylt //
4*3d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
5d7b241e6Sjeremylt //
6*3d8e8822SJeremy 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 
2797a982d89SJeremy L. Thompson /// @}
2807a982d89SJeremy L. Thompson 
28115910d16Sjeremylt /// @cond DOXYGEN_SKIP
28215910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
28315910d16Sjeremylt /// @endcond
28415910d16Sjeremylt 
2857a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
2867a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
2877a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
2887a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
289d7b241e6Sjeremylt /// @{
290d7b241e6Sjeremylt 
2917a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
29245f1e315Sjeremylt const CeedInt CEED_STRIDES_BACKEND[3] = {0};
2937a982d89SJeremy L. Thompson 
2944cc79fe7SJed Brown /// Indicate that no CeedElemRestriction is provided by the user
2957a982d89SJeremy L. Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE =
2967a982d89SJeremy L. Thompson   &ceed_elemrestriction_none;
2977a982d89SJeremy L. Thompson 
298d7b241e6Sjeremylt /**
299b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
300d7b241e6Sjeremylt 
301b11c1e72Sjeremylt   @param ceed         A Ceed object where the CeedElemRestriction will be created
302d1d35e2fSjeremylt   @param num_elem     Number of elements described in the @a offsets array
303d1d35e2fSjeremylt   @param elem_size    Size (number of "nodes") per element
304d1d35e2fSjeremylt   @param num_comp     Number of field components per interpolation node
30595bb1877Svaleriabarra                         (1 for scalar fields)
306d1d35e2fSjeremylt   @param comp_stride  Stride between components for the same L-vector "node".
30795e93d34SJeremy L Thompson                         Data for node i, component j, element k can be found in
30895e93d34SJeremy L Thompson                         the L-vector at index
309d1d35e2fSjeremylt                         offsets[i + k*elem_size] + j*comp_stride.
310d1d35e2fSjeremylt   @param l_size       The size of the L-vector. This vector may be larger than
311d979a051Sjeremylt                         the elements and fields given by this restriction.
312d1d35e2fSjeremylt   @param mem_type     Memory type of the @a offsets array, see CeedMemType
313d1d35e2fSjeremylt   @param copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
314d1d35e2fSjeremylt   @param offsets      Array of shape [@a num_elem, @a elem_size]. Row i holds the
315d979a051Sjeremylt                         ordered list of the offsets (into the input CeedVector)
3168795c945Sjeremylt                         for the unknowns corresponding to element i, where
317d1d35e2fSjeremylt                         0 <= i < @a num_elem. All offsets must be in the range
318d1d35e2fSjeremylt                         [0, @a l_size - 1].
3194ce2993fSjeremylt   @param[out] rstr    Address of the variable where the newly created
320b11c1e72Sjeremylt                         CeedElemRestriction will be stored
321d7b241e6Sjeremylt 
322b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
323dfdf5a53Sjeremylt 
3247a982d89SJeremy L. Thompson   @ref User
325b11c1e72Sjeremylt **/
326d1d35e2fSjeremylt int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size,
327d1d35e2fSjeremylt                               CeedInt num_comp, CeedInt comp_stride,
328e79b91d9SJeremy L Thompson                               CeedSize l_size, CeedMemType mem_type,
329d1d35e2fSjeremylt                               CeedCopyMode copy_mode, const CeedInt *offsets,
3304ce2993fSjeremylt                               CeedElemRestriction *rstr) {
331d7b241e6Sjeremylt   int ierr;
332d7b241e6Sjeremylt 
3335fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
3345fe0d4faSjeremylt     Ceed delegate;
335aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
336aefd8378Sjeremylt     CeedChk(ierr);
3375fe0d4faSjeremylt 
3385fe0d4faSjeremylt     if (!delegate)
339c042f62fSJeremy L Thompson       // LCOV_EXCL_START
340e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
341e15f9bd0SJeremy L Thompson                        "Backend does not support ElemRestrictionCreate");
342c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
3435fe0d4faSjeremylt 
344d1d35e2fSjeremylt     ierr = CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp,
345d1d35e2fSjeremylt                                      comp_stride, l_size, mem_type, copy_mode,
346d979a051Sjeremylt                                      offsets, rstr); CeedChk(ierr);
347e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
3485fe0d4faSjeremylt   }
3495fe0d4faSjeremylt 
3504ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
3514ce2993fSjeremylt   (*rstr)->ceed = ceed;
3529560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
353d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
354d1d35e2fSjeremylt   (*rstr)->num_elem = num_elem;
355d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
356d1d35e2fSjeremylt   (*rstr)->num_comp = num_comp;
357d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
358d1d35e2fSjeremylt   (*rstr)->l_size = l_size;
359d1d35e2fSjeremylt   (*rstr)->num_blk = num_elem;
360d1d35e2fSjeremylt   (*rstr)->blk_size = 1;
361b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 0;
362d1d35e2fSjeremylt   ierr = ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, *rstr);
363d979a051Sjeremylt   CeedChk(ierr);
364e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
365d7b241e6Sjeremylt }
366d7b241e6Sjeremylt 
367d7b241e6Sjeremylt /**
368fc0567d9Srezgarshakeri   @brief Create a CeedElemRestriction with orientation sign
369fc0567d9Srezgarshakeri 
370fc0567d9Srezgarshakeri   @param ceed         A Ceed object where the CeedElemRestriction will be created
371fc0567d9Srezgarshakeri   @param num_elem     Number of elements described in the @a offsets array
372fc0567d9Srezgarshakeri   @param elem_size    Size (number of "nodes") per element
373fc0567d9Srezgarshakeri   @param num_comp     Number of field components per interpolation node
374fc0567d9Srezgarshakeri                         (1 for scalar fields)
375fc0567d9Srezgarshakeri   @param comp_stride  Stride between components for the same L-vector "node".
376fc0567d9Srezgarshakeri                         Data for node i, component j, element k can be found in
377fc0567d9Srezgarshakeri                         the L-vector at index
378fc0567d9Srezgarshakeri                         offsets[i + k*elem_size] + j*comp_stride.
379fc0567d9Srezgarshakeri   @param l_size       The size of the L-vector. This vector may be larger than
380fc0567d9Srezgarshakeri                         the elements and fields given by this restriction.
381fc0567d9Srezgarshakeri   @param mem_type     Memory type of the @a offsets array, see CeedMemType
382fc0567d9Srezgarshakeri   @param copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
383fc0567d9Srezgarshakeri   @param offsets      Array of shape [@a num_elem, @a elem_size]. Row i holds the
384fc0567d9Srezgarshakeri                         ordered list of the offsets (into the input CeedVector)
385fc0567d9Srezgarshakeri                         for the unknowns corresponding to element i, where
386fc0567d9Srezgarshakeri                         0 <= i < @a num_elem. All offsets must be in the range
387fc0567d9Srezgarshakeri                         [0, @a l_size - 1].
388fc0567d9Srezgarshakeri   @param orient       Array of shape [@a num_elem, @a elem_size] with bool false
389fc0567d9Srezgarshakeri                         for positively oriented and true to flip the orientation.
390fc0567d9Srezgarshakeri   @param[out] rstr    Address of the variable where the newly created
391fc0567d9Srezgarshakeri                         CeedElemRestriction will be stored
392fc0567d9Srezgarshakeri 
393fc0567d9Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
394fc0567d9Srezgarshakeri 
395fc0567d9Srezgarshakeri   @ref User
396fc0567d9Srezgarshakeri **/
397fc0567d9Srezgarshakeri int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem,
398fc0567d9Srezgarshakeri                                       CeedInt elem_size, CeedInt num_comp,
399e79b91d9SJeremy L Thompson                                       CeedInt comp_stride, CeedSize l_size,
400fc0567d9Srezgarshakeri                                       CeedMemType mem_type, CeedCopyMode copy_mode,
401fc0567d9Srezgarshakeri                                       const CeedInt *offsets, const bool *orient,
402fc0567d9Srezgarshakeri                                       CeedElemRestriction *rstr) {
403fc0567d9Srezgarshakeri   int ierr;
404fc0567d9Srezgarshakeri 
405c7745053SRezgar Shakeri   if (!ceed->ElemRestrictionCreateOriented) {
406fc0567d9Srezgarshakeri     Ceed delegate;
407fc0567d9Srezgarshakeri     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
408fc0567d9Srezgarshakeri     CeedChk(ierr);
409fc0567d9Srezgarshakeri 
410fc0567d9Srezgarshakeri     if (!delegate)
411fc0567d9Srezgarshakeri       // LCOV_EXCL_START
412fc0567d9Srezgarshakeri       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
41361e7462cSRezgar Shakeri                        "Backend does not implement ElemRestrictionCreateOriented");
414fc0567d9Srezgarshakeri     // LCOV_EXCL_STOP
415fc0567d9Srezgarshakeri 
416fc0567d9Srezgarshakeri     ierr = CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size,
417c7745053SRezgar Shakeri            num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
4184dd06d33Srezgarshakeri            orient, rstr); CeedChk(ierr);
419fc0567d9Srezgarshakeri     return CEED_ERROR_SUCCESS;
420fc0567d9Srezgarshakeri   }
421fc0567d9Srezgarshakeri 
422fc0567d9Srezgarshakeri   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
423fc0567d9Srezgarshakeri   (*rstr)->ceed = ceed;
424fc0567d9Srezgarshakeri   ierr = CeedReference(ceed); CeedChk(ierr);
425fc0567d9Srezgarshakeri   (*rstr)->ref_count = 1;
426fc0567d9Srezgarshakeri   (*rstr)->num_elem = num_elem;
427fc0567d9Srezgarshakeri   (*rstr)->elem_size = elem_size;
428fc0567d9Srezgarshakeri   (*rstr)->num_comp = num_comp;
429fc0567d9Srezgarshakeri   (*rstr)->comp_stride = comp_stride;
430fc0567d9Srezgarshakeri   (*rstr)->l_size = l_size;
431fc0567d9Srezgarshakeri   (*rstr)->num_blk = num_elem;
432fc0567d9Srezgarshakeri   (*rstr)->blk_size = 1;
433b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 1;
4344dd06d33Srezgarshakeri   ierr = ceed->ElemRestrictionCreateOriented(mem_type, copy_mode,
4354dd06d33Srezgarshakeri          offsets, orient, *rstr); CeedChk(ierr);
436fc0567d9Srezgarshakeri   return CEED_ERROR_SUCCESS;
437fc0567d9Srezgarshakeri }
438fc0567d9Srezgarshakeri 
439fc0567d9Srezgarshakeri /**
4407509a596Sjeremylt   @brief Create a strided CeedElemRestriction
441d7b241e6Sjeremylt 
442b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
443d1d35e2fSjeremylt   @param num_elem   Number of elements described by the restriction
444d1d35e2fSjeremylt   @param elem_size  Size (number of "nodes") per element
445d1d35e2fSjeremylt   @param num_comp   Number of field components per interpolation "node"
44695bb1877Svaleriabarra                       (1 for scalar fields)
447d1d35e2fSjeremylt   @param l_size     The size of the L-vector. This vector may be larger than
448d979a051Sjeremylt                       the elements and fields given by this restriction.
4497509a596Sjeremylt   @param strides    Array for strides between [nodes, components, elements].
45095e93d34SJeremy L Thompson                       Data for node i, component j, element k can be found in
45195e93d34SJeremy L Thompson                       the L-vector at index
45295e93d34SJeremy L Thompson                       i*strides[0] + j*strides[1] + k*strides[2].
45395e93d34SJeremy L Thompson                       @a CEED_STRIDES_BACKEND may be used with vectors created
45495e93d34SJeremy L Thompson                       by a Ceed backend.
4554ce2993fSjeremylt   @param rstr       Address of the variable where the newly created
456b11c1e72Sjeremylt                       CeedElemRestriction will be stored
457d7b241e6Sjeremylt 
458b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
459dfdf5a53Sjeremylt 
4607a982d89SJeremy L. Thompson   @ref User
461b11c1e72Sjeremylt **/
462d1d35e2fSjeremylt int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem,
463d1d35e2fSjeremylt                                      CeedInt elem_size,
464e79b91d9SJeremy L Thompson                                      CeedInt num_comp, CeedSize l_size,
4658621c6c6SJeremy L Thompson                                      const CeedInt strides[3],
466f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
467d7b241e6Sjeremylt   int ierr;
468d7b241e6Sjeremylt 
4695fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
4705fe0d4faSjeremylt     Ceed delegate;
471aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
472aefd8378Sjeremylt     CeedChk(ierr);
4735fe0d4faSjeremylt 
4745fe0d4faSjeremylt     if (!delegate)
475c042f62fSJeremy L Thompson       // LCOV_EXCL_START
476e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
477e15f9bd0SJeremy L Thompson                        "Backend does not support ElemRestrictionCreate");
478c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
4795fe0d4faSjeremylt 
480d1d35e2fSjeremylt     ierr = CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp,
481d1d35e2fSjeremylt                                             l_size, strides, rstr);
482d979a051Sjeremylt     CeedChk(ierr);
483e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
4845fe0d4faSjeremylt   }
4855fe0d4faSjeremylt 
4864ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
4874ce2993fSjeremylt   (*rstr)->ceed = ceed;
4889560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
489d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
490d1d35e2fSjeremylt   (*rstr)->num_elem = num_elem;
491d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
492d1d35e2fSjeremylt   (*rstr)->num_comp = num_comp;
493d1d35e2fSjeremylt   (*rstr)->l_size = l_size;
494d1d35e2fSjeremylt   (*rstr)->num_blk = num_elem;
495d1d35e2fSjeremylt   (*rstr)->blk_size = 1;
496b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 0;
4977509a596Sjeremylt   ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr);
4987509a596Sjeremylt   for (int i=0; i<3; i++)
4997509a596Sjeremylt     (*rstr)->strides[i] = strides[i];
5001dfeef1dSjeremylt   ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL,
5011dfeef1dSjeremylt                                      *rstr);
5024b8bea3bSJed Brown   CeedChk(ierr);
503e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
504d7b241e6Sjeremylt }
505d7b241e6Sjeremylt 
506d7b241e6Sjeremylt /**
507b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
508d7b241e6Sjeremylt 
509d7b241e6Sjeremylt   @param ceed         A Ceed object where the CeedElemRestriction will be created.
510d1d35e2fSjeremylt   @param num_elem     Number of elements described in the @a offsets array.
511d1d35e2fSjeremylt   @param elem_size    Size (number of unknowns) per element
512d1d35e2fSjeremylt   @param blk_size     Number of elements in a block
513d1d35e2fSjeremylt   @param num_comp     Number of field components per interpolation node
51495bb1877Svaleriabarra                         (1 for scalar fields)
515d1d35e2fSjeremylt   @param comp_stride  Stride between components for the same L-vector "node".
51695e93d34SJeremy L Thompson                         Data for node i, component j, element k can be found in
51795e93d34SJeremy L Thompson                         the L-vector at index
518d1d35e2fSjeremylt                         offsets[i + k*elem_size] + j*comp_stride.
519d1d35e2fSjeremylt   @param l_size       The size of the L-vector. This vector may be larger than
520d979a051Sjeremylt                         the elements and fields given by this restriction.
521d1d35e2fSjeremylt   @param mem_type     Memory type of the @a offsets array, see CeedMemType
522d1d35e2fSjeremylt   @param copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
523d1d35e2fSjeremylt   @param offsets      Array of shape [@a num_elem, @a elem_size]. Row i holds the
524d979a051Sjeremylt                         ordered list of the offsets (into the input CeedVector)
5258795c945Sjeremylt                         for the unknowns corresponding to element i, where
526d1d35e2fSjeremylt                         0 <= i < @a num_elem. All offsets must be in the range
527d1d35e2fSjeremylt                         [0, @a l_size - 1]. The backend will permute and pad this
5288795c945Sjeremylt                         array to the desired ordering for the blocksize, which is
5298795c945Sjeremylt                         typically given by the backend. The default reordering is
5308795c945Sjeremylt                         to interlace elements.
5314ce2993fSjeremylt   @param rstr         Address of the variable where the newly created
532b11c1e72Sjeremylt                         CeedElemRestriction will be stored
533d7b241e6Sjeremylt 
534b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
535dfdf5a53Sjeremylt 
5367a982d89SJeremy L. Thompson   @ref Backend
537b11c1e72Sjeremylt  **/
538d1d35e2fSjeremylt int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem,
539d1d35e2fSjeremylt                                      CeedInt elem_size,
540d1d35e2fSjeremylt                                      CeedInt blk_size, CeedInt num_comp,
541e79b91d9SJeremy L Thompson                                      CeedInt comp_stride, CeedSize l_size,
542d1d35e2fSjeremylt                                      CeedMemType mem_type, CeedCopyMode copy_mode,
543d979a051Sjeremylt                                      const CeedInt *offsets,
5444ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
545d7b241e6Sjeremylt   int ierr;
546d1d35e2fSjeremylt   CeedInt *blk_offsets;
547d1d35e2fSjeremylt   CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
548d7b241e6Sjeremylt 
5495fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
5505fe0d4faSjeremylt     Ceed delegate;
551aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
552aefd8378Sjeremylt     CeedChk(ierr);
5535fe0d4faSjeremylt 
5545fe0d4faSjeremylt     if (!delegate)
555c042f62fSJeremy L Thompson       // LCOV_EXCL_START
556e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support "
5571d102b48SJeremy L Thompson                        "ElemRestrictionCreateBlocked");
558c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
5595fe0d4faSjeremylt 
560d1d35e2fSjeremylt     ierr = CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, blk_size,
561d1d35e2fSjeremylt                                             num_comp, comp_stride, l_size, mem_type,
562d1d35e2fSjeremylt                                             copy_mode, offsets, rstr);
563d979a051Sjeremylt     CeedChk(ierr);
564e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
5655fe0d4faSjeremylt   }
566d7b241e6Sjeremylt 
5674ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
568d7b241e6Sjeremylt 
569d1d35e2fSjeremylt   ierr = CeedCalloc(num_blk*blk_size*elem_size, &blk_offsets); CeedChk(ierr);
570d1d35e2fSjeremylt   ierr = CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size,
571d1d35e2fSjeremylt                                elem_size); CeedChk(ierr);
572d7b241e6Sjeremylt 
5734ce2993fSjeremylt   (*rstr)->ceed = ceed;
5749560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
575d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
576d1d35e2fSjeremylt   (*rstr)->num_elem = num_elem;
577d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
578d1d35e2fSjeremylt   (*rstr)->num_comp = num_comp;
579d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
580d1d35e2fSjeremylt   (*rstr)->l_size = l_size;
581d1d35e2fSjeremylt   (*rstr)->num_blk = num_blk;
582d1d35e2fSjeremylt   (*rstr)->blk_size = blk_size;
583b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 0;
584667bc5fcSjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
585d1d35e2fSjeremylt          (const CeedInt *) blk_offsets, *rstr); CeedChk(ierr);
586d1d35e2fSjeremylt   if (copy_mode == CEED_OWN_POINTER) {
587d979a051Sjeremylt     ierr = CeedFree(&offsets); CeedChk(ierr);
5881d102b48SJeremy L Thompson   }
589e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
590d7b241e6Sjeremylt }
591d7b241e6Sjeremylt 
592b11c1e72Sjeremylt /**
5937509a596Sjeremylt   @brief Create a blocked strided CeedElemRestriction
5947509a596Sjeremylt 
5957509a596Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
596d1d35e2fSjeremylt   @param num_elem   Number of elements described by the restriction
597d1d35e2fSjeremylt   @param elem_size  Size (number of "nodes") per element
598d1d35e2fSjeremylt   @param blk_size   Number of elements in a block
599d1d35e2fSjeremylt   @param num_comp   Number of field components per interpolation node
6007509a596Sjeremylt                       (1 for scalar fields)
601d1d35e2fSjeremylt   @param l_size     The size of the L-vector. This vector may be larger than
602d979a051Sjeremylt                       the elements and fields given by this restriction.
6037509a596Sjeremylt   @param strides    Array for strides between [nodes, components, elements].
60495e93d34SJeremy L Thompson                       Data for node i, component j, element k can be found in
60595e93d34SJeremy L Thompson                       the L-vector at index
60695e93d34SJeremy L Thompson                       i*strides[0] + j*strides[1] + k*strides[2].
60795e93d34SJeremy L Thompson                       @a CEED_STRIDES_BACKEND may be used with vectors created
60895e93d34SJeremy L Thompson                       by a Ceed backend.
6097509a596Sjeremylt   @param rstr       Address of the variable where the newly created
6107509a596Sjeremylt                       CeedElemRestriction will be stored
6117509a596Sjeremylt 
6127509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
6137509a596Sjeremylt 
6147a982d89SJeremy L. Thompson   @ref User
6157509a596Sjeremylt **/
616d1d35e2fSjeremylt int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem,
617e79b91d9SJeremy L Thompson     CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedSize l_size,
6188621c6c6SJeremy L Thompson     const CeedInt strides[3], CeedElemRestriction *rstr) {
6197509a596Sjeremylt   int ierr;
620d1d35e2fSjeremylt   CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
6217509a596Sjeremylt 
6227509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
6237509a596Sjeremylt     Ceed delegate;
6247509a596Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
6257509a596Sjeremylt     CeedChk(ierr);
6267509a596Sjeremylt 
6277509a596Sjeremylt     if (!delegate)
6287509a596Sjeremylt       // LCOV_EXCL_START
629e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support "
6307509a596Sjeremylt                        "ElemRestrictionCreateBlocked");
6317509a596Sjeremylt     // LCOV_EXCL_STOP
6327509a596Sjeremylt 
633d1d35e2fSjeremylt     ierr = CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size,
634d1d35e2fSjeremylt            blk_size, num_comp, l_size, strides, rstr); CeedChk(ierr);
635e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6367509a596Sjeremylt   }
6377509a596Sjeremylt 
6387509a596Sjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
6397509a596Sjeremylt 
6407509a596Sjeremylt   (*rstr)->ceed = ceed;
6419560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
642d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
643d1d35e2fSjeremylt   (*rstr)->num_elem = num_elem;
644d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
645d1d35e2fSjeremylt   (*rstr)->num_comp = num_comp;
646d1d35e2fSjeremylt   (*rstr)->l_size = l_size;
647d1d35e2fSjeremylt   (*rstr)->num_blk = num_blk;
648d1d35e2fSjeremylt   (*rstr)->blk_size = blk_size;
649b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 0;
6507509a596Sjeremylt   ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr);
6517509a596Sjeremylt   for (int i=0; i<3; i++)
6527509a596Sjeremylt     (*rstr)->strides[i] = strides[i];
6537509a596Sjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
6547509a596Sjeremylt          NULL, *rstr); CeedChk(ierr);
655e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6567509a596Sjeremylt }
6577509a596Sjeremylt 
6587509a596Sjeremylt /**
6599560d06aSjeremylt   @brief Copy the pointer to a CeedElemRestriction. Both pointers should
6609560d06aSjeremylt            be destroyed with `CeedElemRestrictionDestroy()`;
6619560d06aSjeremylt            Note: If `*rstr_copy` is non-NULL, then it is assumed that
6629560d06aSjeremylt            `*rstr_copy` is a pointer to a CeedElemRestriction. This
6639560d06aSjeremylt            CeedElemRestriction will be destroyed if `*rstr_copy` is the
6649560d06aSjeremylt            only reference to this CeedElemRestriction.
6659560d06aSjeremylt 
6669560d06aSjeremylt   @param rstr            CeedElemRestriction to copy reference to
6679560d06aSjeremylt   @param[out] rstr_copy  Variable to store copied reference
6689560d06aSjeremylt 
6699560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
6709560d06aSjeremylt 
6719560d06aSjeremylt   @ref User
6729560d06aSjeremylt **/
6739560d06aSjeremylt int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr,
6749560d06aSjeremylt                                      CeedElemRestriction *rstr_copy) {
6759560d06aSjeremylt   int ierr;
6769560d06aSjeremylt 
6779560d06aSjeremylt   ierr = CeedElemRestrictionReference(rstr); CeedChk(ierr);
6789560d06aSjeremylt   ierr = CeedElemRestrictionDestroy(rstr_copy); CeedChk(ierr);
6799560d06aSjeremylt   *rstr_copy = rstr;
6809560d06aSjeremylt   return CEED_ERROR_SUCCESS;
6819560d06aSjeremylt }
6829560d06aSjeremylt 
6839560d06aSjeremylt /**
684b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
685b11c1e72Sjeremylt 
6864ce2993fSjeremylt   @param rstr   CeedElemRestriction
687d1d35e2fSjeremylt   @param l_vec  The address of the L-vector to be created, or NULL
688d1d35e2fSjeremylt   @param e_vec  The address of the E-vector to be created, or NULL
689b11c1e72Sjeremylt 
690b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
691dfdf5a53Sjeremylt 
6927a982d89SJeremy L. Thompson   @ref User
693b11c1e72Sjeremylt **/
694d1d35e2fSjeremylt int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec,
695d1d35e2fSjeremylt                                     CeedVector *e_vec) {
696d7b241e6Sjeremylt   int ierr;
697d1d35e2fSjeremylt   CeedInt e_size, l_size;
698d1d35e2fSjeremylt   l_size = rstr->l_size;
699d1d35e2fSjeremylt   e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
700d1d35e2fSjeremylt   if (l_vec) {
701d1d35e2fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, l_size, l_vec); CeedChk(ierr);
702d7b241e6Sjeremylt   }
703d1d35e2fSjeremylt   if (e_vec) {
704d1d35e2fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, e_size, e_vec); CeedChk(ierr);
705d7b241e6Sjeremylt   }
706e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
707d7b241e6Sjeremylt }
708d7b241e6Sjeremylt 
709d7b241e6Sjeremylt /**
710d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
711d7b241e6Sjeremylt 
7124ce2993fSjeremylt   @param rstr    CeedElemRestriction
713d1d35e2fSjeremylt   @param t_mode  Apply restriction or transpose
714d1d35e2fSjeremylt   @param u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
715d1d35e2fSjeremylt   @param ru      Output vector (of shape [@a num_elem * @a elem_size] when
716d1d35e2fSjeremylt                    t_mode=@ref CEED_NOTRANSPOSE). Ordering of the e-vector is decided
7177aaeacdcSjeremylt                    by the backend.
7184cc79fe7SJed Brown   @param request Request or @ref CEED_REQUEST_IMMEDIATE
719b11c1e72Sjeremylt 
720b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
721dfdf5a53Sjeremylt 
7227a982d89SJeremy L. Thompson   @ref User
723b11c1e72Sjeremylt **/
724d1d35e2fSjeremylt int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode,
725a8d32208Sjeremylt                              CeedVector u, CeedVector ru,
726a8d32208Sjeremylt                              CeedRequest *request) {
727d7b241e6Sjeremylt   CeedInt m, n;
728d7b241e6Sjeremylt   int ierr;
729d7b241e6Sjeremylt 
730d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
731d1d35e2fSjeremylt     m = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
732d1d35e2fSjeremylt     n = rstr->l_size;
733d7b241e6Sjeremylt   } else {
734d1d35e2fSjeremylt     m = rstr->l_size;
735d1d35e2fSjeremylt     n = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
736d7b241e6Sjeremylt   }
737d7b241e6Sjeremylt   if (n != u->length)
738c042f62fSJeremy L Thompson     // LCOV_EXCL_START
739e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
740e15f9bd0SJeremy L Thompson                      "Input vector size %d not compatible with "
7411d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
742c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
743a8d32208Sjeremylt   if (m != ru->length)
744c042f62fSJeremy L Thompson     // LCOV_EXCL_START
745e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
746e15f9bd0SJeremy L Thompson                      "Output vector size %d not compatible with "
747a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
748c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
749d1d35e2fSjeremylt   ierr = rstr->Apply(rstr, t_mode, u, ru, request); CeedChk(ierr);
750e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
751d7b241e6Sjeremylt }
752d7b241e6Sjeremylt 
753d7b241e6Sjeremylt /**
754d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
755be9261b7Sjeremylt 
756be9261b7Sjeremylt   @param rstr    CeedElemRestriction
7571f37b403Sjeremylt   @param block   Block number to restrict to/from, i.e. block=0 will handle
758d1d35e2fSjeremylt                    elements [0 : blk_size] and block=3 will handle elements
759d1d35e2fSjeremylt                    [3*blk_size : 4*blk_size]
760d1d35e2fSjeremylt   @param t_mode  Apply restriction or transpose
761d1d35e2fSjeremylt   @param u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
762d1d35e2fSjeremylt   @param ru      Output vector (of shape [@a blk_size * @a elem_size] when
763d1d35e2fSjeremylt                    t_mode=@ref CEED_NOTRANSPOSE). Ordering of the e-vector is decided
7647aaeacdcSjeremylt                    by the backend.
7654cc79fe7SJed Brown   @param request Request or @ref CEED_REQUEST_IMMEDIATE
766be9261b7Sjeremylt 
767be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
768be9261b7Sjeremylt 
7697a982d89SJeremy L. Thompson   @ref Backend
770be9261b7Sjeremylt **/
771be9261b7Sjeremylt int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block,
772d1d35e2fSjeremylt                                   CeedTransposeMode t_mode, CeedVector u,
773a8d32208Sjeremylt                                   CeedVector ru, CeedRequest *request) {
774be9261b7Sjeremylt   CeedInt m, n;
775be9261b7Sjeremylt   int ierr;
776be9261b7Sjeremylt 
777d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
778d1d35e2fSjeremylt     m = rstr->blk_size * rstr->elem_size * rstr->num_comp;
779d1d35e2fSjeremylt     n = rstr->l_size;
780be9261b7Sjeremylt   } else {
781d1d35e2fSjeremylt     m = rstr->l_size;
782d1d35e2fSjeremylt     n = rstr->blk_size * rstr->elem_size * rstr->num_comp;
783be9261b7Sjeremylt   }
784be9261b7Sjeremylt   if (n != u->length)
785c042f62fSJeremy L Thompson     // LCOV_EXCL_START
786e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
787e15f9bd0SJeremy L Thompson                      "Input vector size %d not compatible with "
7881d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
789c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
790a8d32208Sjeremylt   if (m != ru->length)
791c042f62fSJeremy L Thompson     // LCOV_EXCL_START
792e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
793e15f9bd0SJeremy L Thompson                      "Output vector size %d not compatible with "
794a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
795c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
796d1d35e2fSjeremylt   if (rstr->blk_size*block > rstr->num_elem)
797c042f62fSJeremy L Thompson     // LCOV_EXCL_START
798e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
799e15f9bd0SJeremy L Thompson                      "Cannot retrieve block %d, element %d > "
800d1d35e2fSjeremylt                      "total elements %d", block, rstr->blk_size*block,
801d1d35e2fSjeremylt                      rstr->num_elem);
802c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
803d1d35e2fSjeremylt   ierr = rstr->ApplyBlock(rstr, block, t_mode, u, ru, request);
804be9261b7Sjeremylt   CeedChk(ierr);
805e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
806be9261b7Sjeremylt }
807be9261b7Sjeremylt 
808be9261b7Sjeremylt /**
809b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedElemRestriction
810b7c9bbdaSJeremy L Thompson 
811b7c9bbdaSJeremy L Thompson   @param rstr       CeedElemRestriction
812b7c9bbdaSJeremy L Thompson   @param[out] ceed  Variable to store Ceed
813b7c9bbdaSJeremy L Thompson 
814b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
815b7c9bbdaSJeremy L Thompson 
816b7c9bbdaSJeremy L Thompson   @ref Advanced
817b7c9bbdaSJeremy L Thompson **/
818b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
819b7c9bbdaSJeremy L Thompson   *ceed = rstr->ceed;
820b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
821b7c9bbdaSJeremy L Thompson }
822b7c9bbdaSJeremy L Thompson 
823b7c9bbdaSJeremy L Thompson /**
824d979a051Sjeremylt   @brief Get the L-vector component stride
825a681ae63Sjeremylt 
826a681ae63Sjeremylt   @param rstr              CeedElemRestriction
827d1d35e2fSjeremylt   @param[out] comp_stride  Variable to store component stride
828a681ae63Sjeremylt 
829a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
830a681ae63Sjeremylt 
831b7c9bbdaSJeremy L Thompson   @ref Advanced
832a681ae63Sjeremylt **/
833d979a051Sjeremylt int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr,
834d1d35e2fSjeremylt                                      CeedInt *comp_stride) {
835d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
836e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
837a681ae63Sjeremylt }
838a681ae63Sjeremylt 
839a681ae63Sjeremylt /**
840a681ae63Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
841a681ae63Sjeremylt 
842a681ae63Sjeremylt   @param rstr           CeedElemRestriction
843d1d35e2fSjeremylt   @param[out] num_elem  Variable to store number of elements
844a681ae63Sjeremylt 
845a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
846a681ae63Sjeremylt 
847b7c9bbdaSJeremy L Thompson   @ref Advanced
848a681ae63Sjeremylt **/
849a681ae63Sjeremylt int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
850d1d35e2fSjeremylt                                       CeedInt *num_elem) {
851d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
852e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
853a681ae63Sjeremylt }
854a681ae63Sjeremylt 
855a681ae63Sjeremylt /**
856a681ae63Sjeremylt   @brief Get the size of elements in the CeedElemRestriction
857a681ae63Sjeremylt 
858a681ae63Sjeremylt   @param rstr            CeedElemRestriction
859d1d35e2fSjeremylt   @param[out] elem_size  Variable to store size of elements
860a681ae63Sjeremylt 
861a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
862a681ae63Sjeremylt 
863b7c9bbdaSJeremy L Thompson   @ref Advanced
864a681ae63Sjeremylt **/
865a681ae63Sjeremylt int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
866d1d35e2fSjeremylt                                       CeedInt *elem_size) {
867d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
868e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
869a681ae63Sjeremylt }
870a681ae63Sjeremylt 
871a681ae63Sjeremylt /**
872d979a051Sjeremylt   @brief Get the size of the l-vector for a CeedElemRestriction
873a681ae63Sjeremylt 
874a681ae63Sjeremylt   @param rstr         CeedElemRestriction
875d1d35e2fSjeremylt   @param[out] l_size  Variable to store number of nodes
876a681ae63Sjeremylt 
877a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
878a681ae63Sjeremylt 
879b7c9bbdaSJeremy L Thompson   @ref Advanced
880a681ae63Sjeremylt **/
881d979a051Sjeremylt int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr,
882e79b91d9SJeremy L Thompson                                       CeedSize *l_size) {
883d1d35e2fSjeremylt   *l_size = rstr->l_size;
884e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
885a681ae63Sjeremylt }
886a681ae63Sjeremylt 
887a681ae63Sjeremylt /**
888a681ae63Sjeremylt   @brief Get the number of components in the elements of a
889a681ae63Sjeremylt          CeedElemRestriction
890a681ae63Sjeremylt 
891a681ae63Sjeremylt   @param rstr           CeedElemRestriction
892d1d35e2fSjeremylt   @param[out] num_comp  Variable to store number of components
893a681ae63Sjeremylt 
894a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
895a681ae63Sjeremylt 
896b7c9bbdaSJeremy L Thompson   @ref Advanced
897a681ae63Sjeremylt **/
898a681ae63Sjeremylt int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
899d1d35e2fSjeremylt                                         CeedInt *num_comp) {
900d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
901e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
902a681ae63Sjeremylt }
903a681ae63Sjeremylt 
904a681ae63Sjeremylt /**
905a681ae63Sjeremylt   @brief Get the number of blocks in a CeedElemRestriction
906a681ae63Sjeremylt 
907a681ae63Sjeremylt   @param rstr            CeedElemRestriction
908d1d35e2fSjeremylt   @param[out] num_block  Variable to store number of blocks
909a681ae63Sjeremylt 
910a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
911a681ae63Sjeremylt 
912b7c9bbdaSJeremy L Thompson   @ref Advanced
913a681ae63Sjeremylt **/
914a681ae63Sjeremylt int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
915d1d35e2fSjeremylt                                     CeedInt *num_block) {
916d1d35e2fSjeremylt   *num_block = rstr->num_blk;
917e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
918a681ae63Sjeremylt }
919a681ae63Sjeremylt 
920a681ae63Sjeremylt /**
921a681ae63Sjeremylt   @brief Get the size of blocks in the CeedElemRestriction
922a681ae63Sjeremylt 
923a681ae63Sjeremylt   @param rstr           CeedElemRestriction
924d1d35e2fSjeremylt   @param[out] blk_size  Variable to store size of blocks
925a681ae63Sjeremylt 
926a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
927a681ae63Sjeremylt 
928b7c9bbdaSJeremy L Thompson   @ref Advanced
929a681ae63Sjeremylt **/
930a681ae63Sjeremylt int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
931d1d35e2fSjeremylt                                     CeedInt *blk_size) {
932d1d35e2fSjeremylt   *blk_size = rstr->blk_size;
933e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
934a681ae63Sjeremylt }
935a681ae63Sjeremylt 
936a681ae63Sjeremylt /**
937d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
9381469ee4dSjeremylt 
9391469ee4dSjeremylt   @param rstr       CeedElemRestriction
940d1d35e2fSjeremylt   @param[out] mult  Vector to store multiplicity (of size l_size)
9411469ee4dSjeremylt 
9421469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
9431469ee4dSjeremylt 
9447a982d89SJeremy L. Thompson   @ref User
9451469ee4dSjeremylt **/
9461469ee4dSjeremylt int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr,
9471469ee4dSjeremylt                                        CeedVector mult) {
9481469ee4dSjeremylt   int ierr;
949d1d35e2fSjeremylt   CeedVector e_vec;
9501469ee4dSjeremylt 
95125509ebbSRezgar Shakeri   // Create e_vec to hold intermediate computation in E^T (E 1)
952d1d35e2fSjeremylt   ierr = CeedElemRestrictionCreateVector(rstr, NULL, &e_vec); CeedChk(ierr);
9531469ee4dSjeremylt 
95425509ebbSRezgar Shakeri   // Compute e_vec = E * 1
95525509ebbSRezgar Shakeri   ierr = CeedVectorSetValue(mult, 1.0); CeedChk(ierr);
95625509ebbSRezgar Shakeri   ierr = CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec,
95725509ebbSRezgar Shakeri                                   CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
95825509ebbSRezgar Shakeri   // Compute multiplicity, mult = E^T * e_vec = E^T (E 1)
95925509ebbSRezgar Shakeri   ierr = CeedVectorSetValue(mult, 0.0); CeedChk(ierr);
960d1d35e2fSjeremylt   ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult,
961efc78312Sjeremylt                                   CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
9621469ee4dSjeremylt   // Cleanup
963d1d35e2fSjeremylt   ierr = CeedVectorDestroy(&e_vec); CeedChk(ierr);
964e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
9651469ee4dSjeremylt }
9661469ee4dSjeremylt 
9671469ee4dSjeremylt /**
968f02ca4a2SJed Brown   @brief View a CeedElemRestriction
969f02ca4a2SJed Brown 
970f02ca4a2SJed Brown   @param[in] rstr    CeedElemRestriction to view
971f02ca4a2SJed Brown   @param[in] stream  Stream to write; typically stdout/stderr or a file
972f02ca4a2SJed Brown 
973f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
974f02ca4a2SJed Brown 
9757a982d89SJeremy L. Thompson   @ref User
976f02ca4a2SJed Brown **/
977f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
9787509a596Sjeremylt   char stridesstr[500];
9797509a596Sjeremylt   if (rstr->strides)
9807509a596Sjeremylt     sprintf(stridesstr, "[%d, %d, %d]", rstr->strides[0], rstr->strides[1],
9817509a596Sjeremylt             rstr->strides[2]);
982d979a051Sjeremylt   else
983d1d35e2fSjeremylt     sprintf(stridesstr, "%d", rstr->comp_stride);
9847509a596Sjeremylt 
9855b76854bSJeremy L Thompson   fprintf(stream, "%sCeedElemRestriction from (%td, %d) to %d elements with %d "
986d1d35e2fSjeremylt           "nodes each and %s %s\n", rstr->blk_size > 1 ? "Blocked " : "",
987d1d35e2fSjeremylt           rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
988d979a051Sjeremylt           rstr->strides ? "strides" : "component stride", stridesstr);
989e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
990f02ca4a2SJed Brown }
991f02ca4a2SJed Brown 
992f02ca4a2SJed Brown /**
993b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
994b11c1e72Sjeremylt 
9954ce2993fSjeremylt   @param rstr  CeedElemRestriction to destroy
996b11c1e72Sjeremylt 
997b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
998dfdf5a53Sjeremylt 
9997a982d89SJeremy L. Thompson   @ref User
1000b11c1e72Sjeremylt **/
10014ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
1002d7b241e6Sjeremylt   int ierr;
1003d7b241e6Sjeremylt 
1004d1d35e2fSjeremylt   if (!*rstr || --(*rstr)->ref_count > 0) return CEED_ERROR_SUCCESS;
1005d1d35e2fSjeremylt   if ((*rstr)->num_readers)
10068229195eSjeremylt     // LCOV_EXCL_START
1007e15f9bd0SJeremy L Thompson     return CeedError((*rstr)->ceed, CEED_ERROR_ACCESS,
1008e15f9bd0SJeremy L Thompson                      "Cannot destroy CeedElemRestriction, "
1009430758c8SJeremy L Thompson                      "a process has read access to the offset data");
10108229195eSjeremylt   // LCOV_EXCL_STOP
10114ce2993fSjeremylt   if ((*rstr)->Destroy) {
10124ce2993fSjeremylt     ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr);
1013d7b241e6Sjeremylt   }
10147509a596Sjeremylt   ierr = CeedFree(&(*rstr)->strides); CeedChk(ierr);
10154ce2993fSjeremylt   ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr);
10164ce2993fSjeremylt   ierr = CeedFree(rstr); CeedChk(ierr);
1017e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1018d7b241e6Sjeremylt }
1019d7b241e6Sjeremylt 
1020d7b241e6Sjeremylt /// @}
1021