xref: /libCEED/interface/ceed-elemrestriction.c (revision 0036de2c0ad807bd8ab213cac28d33186520da16)
1d7b241e6Sjeremylt // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2d7b241e6Sjeremylt // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3d7b241e6Sjeremylt // reserved. See files LICENSE and NOTICE for details.
4d7b241e6Sjeremylt //
5d7b241e6Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software
6d7b241e6Sjeremylt // libraries and APIs for efficient high-order finite element and spectral
7d7b241e6Sjeremylt // element discretizations for exascale applications. For more information and
8d7b241e6Sjeremylt // source code availability see http://github.com/ceed.
9d7b241e6Sjeremylt //
10d7b241e6Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11d7b241e6Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office
12d7b241e6Sjeremylt // of Science and the National Nuclear Security Administration) responsible for
13d7b241e6Sjeremylt // the planning and preparation of a capable exascale ecosystem, including
14d7b241e6Sjeremylt // software, applications, hardware, advanced system engineering and early
15d7b241e6Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative.
16d7b241e6Sjeremylt 
17d7b241e6Sjeremylt #include <ceed-impl.h>
18d863ab9bSjeremylt #include <ceed-backend.h>
19d7b241e6Sjeremylt 
20d7b241e6Sjeremylt /// @file
21d7b241e6Sjeremylt /// Implementation of public CeedElemRestriction interfaces
22d7b241e6Sjeremylt ///
23dfdf5a53Sjeremylt /// @addtogroup CeedElemRestriction
24d7b241e6Sjeremylt /// @{
25d7b241e6Sjeremylt 
26d7b241e6Sjeremylt /**
27b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
28d7b241e6Sjeremylt 
29b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
3061dbc9d2Sjeremylt   @param imode      Ordering of the ncomp components, i.e. it specifies
31a8d32208Sjeremylt                       the ordering of the components of the L-vector used
3261dbc9d2Sjeremylt                       by this CeedElemRestriction. CEED_NONINTERLACED indicates
3361dbc9d2Sjeremylt                       the component is the outermost index and CEED_INTERLACED
34a8d32208Sjeremylt                       indicates the component is the innermost index in
35a8d32208Sjeremylt                       ordering of the L-vector.
36b11c1e72Sjeremylt   @param nelem      Number of elements described in the @a indices array
37b11c1e72Sjeremylt   @param elemsize   Size (number of "nodes") per element
388795c945Sjeremylt   @param nnodes     The number of nodes in the L-vector. The input CeedVector
398795c945Sjeremylt                       to which the restriction will be applied is of size
408795c945Sjeremylt                       @a nnodes * @a ncomp. This size may include data
41d7b241e6Sjeremylt                       used by other CeedElemRestriction objects describing
42d7b241e6Sjeremylt                       different types of elements.
43b11c1e72Sjeremylt   @param ncomp      Number of field components per interpolation node
4495bb1877Svaleriabarra                       (1 for scalar fields)
45b11c1e72Sjeremylt   @param mtype      Memory type of the @a indices array, see CeedMemType
46b11c1e72Sjeremylt   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
478795c945Sjeremylt   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
488795c945Sjeremylt                       ordered list of the indices (into the input CeedVector)
498795c945Sjeremylt                       for the unknowns corresponding to element i, where
5034138859Sjeremylt                       0 <= i < @a nelem. All indices must be in the range
5123e8ed12Sjeremylt                       [0, @a nnodes - 1].
524ce2993fSjeremylt   @param[out] rstr  Address of the variable where the newly created
53b11c1e72Sjeremylt                       CeedElemRestriction will be stored
54d7b241e6Sjeremylt 
55b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
56dfdf5a53Sjeremylt 
57dfdf5a53Sjeremylt   @ref Basic
58b11c1e72Sjeremylt **/
5961dbc9d2Sjeremylt int CeedElemRestrictionCreate(Ceed ceed, CeedInterlaceMode imode,
607509a596Sjeremylt                               CeedInt nelem, CeedInt elemsize, CeedInt nnodes,
617509a596Sjeremylt                               CeedInt ncomp, CeedMemType mtype,
627509a596Sjeremylt                               CeedCopyMode cmode, const CeedInt *indices,
634ce2993fSjeremylt                               CeedElemRestriction *rstr) {
64d7b241e6Sjeremylt   int ierr;
65d7b241e6Sjeremylt 
665fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
675fe0d4faSjeremylt     Ceed delegate;
68aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
69aefd8378Sjeremylt     CeedChk(ierr);
705fe0d4faSjeremylt 
715fe0d4faSjeremylt     if (!delegate)
72c042f62fSJeremy L Thompson       // LCOV_EXCL_START
73d7b241e6Sjeremylt       return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
74c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
755fe0d4faSjeremylt 
7661dbc9d2Sjeremylt     ierr = CeedElemRestrictionCreate(delegate, imode, nelem, elemsize,
778795c945Sjeremylt                                      nnodes, ncomp, mtype, cmode,
784ce2993fSjeremylt                                      indices, rstr); CeedChk(ierr);
795fe0d4faSjeremylt     return 0;
805fe0d4faSjeremylt   }
815fe0d4faSjeremylt 
824ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
834ce2993fSjeremylt   (*rstr)->ceed = ceed;
84d7b241e6Sjeremylt   ceed->refcount++;
854ce2993fSjeremylt   (*rstr)->refcount = 1;
8661dbc9d2Sjeremylt   (*rstr)->imode = imode;
874ce2993fSjeremylt   (*rstr)->nelem = nelem;
884ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
898795c945Sjeremylt   (*rstr)->nnodes = nnodes;
904ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
914ce2993fSjeremylt   (*rstr)->nblk = nelem;
924ce2993fSjeremylt   (*rstr)->blksize = 1;
934ce2993fSjeremylt   ierr = ceed->ElemRestrictionCreate(mtype, cmode, indices, *rstr); CeedChk(ierr);
94d7b241e6Sjeremylt   return 0;
95d7b241e6Sjeremylt }
96d7b241e6Sjeremylt 
97d7b241e6Sjeremylt /**
987509a596Sjeremylt   @brief Create a strided CeedElemRestriction
99d7b241e6Sjeremylt 
100b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
1017509a596Sjeremylt   @param nelem      Number of elements described by the restriction
102b11c1e72Sjeremylt   @param elemsize   Size (number of "nodes") per element
1038795c945Sjeremylt   @param nnodes     The number of nodes in the L-vector. The input CeedVector
1048795c945Sjeremylt                       to which the restriction will be applied is of size
1058795c945Sjeremylt                       @a nnodes * @a ncomp. This size may include data
106d7b241e6Sjeremylt                       used by other CeedElemRestriction objects describing
1078795c945Sjeremylt                       different types of elements.
108b11c1e72Sjeremylt   @param ncomp      Number of field components per interpolation node
10995bb1877Svaleriabarra                       (1 for scalar fields)
1107509a596Sjeremylt   @param strides    Array for strides between [nodes, components, elements].
1117509a596Sjeremylt                       The data for node i, component j, element k in the
1127509a596Sjeremylt                       L-vector is given by
1137509a596Sjeremylt                         i*strides[0] + j*strides[1] + k*strides[2]
1144ce2993fSjeremylt   @param rstr       Address of the variable where the newly created
115b11c1e72Sjeremylt                       CeedElemRestriction will be stored
116d7b241e6Sjeremylt 
117b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
118dfdf5a53Sjeremylt 
119dfdf5a53Sjeremylt   @ref Basic
120b11c1e72Sjeremylt **/
1217509a596Sjeremylt int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt nelem, CeedInt elemsize,
122a8d32208Sjeremylt                                      CeedInt nnodes, CeedInt ncomp,
1237509a596Sjeremylt                                      CeedInt strides[3],
124f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
125d7b241e6Sjeremylt   int ierr;
126d7b241e6Sjeremylt 
1275fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
1285fe0d4faSjeremylt     Ceed delegate;
129aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
130aefd8378Sjeremylt     CeedChk(ierr);
1315fe0d4faSjeremylt 
1325fe0d4faSjeremylt     if (!delegate)
133c042f62fSJeremy L Thompson       // LCOV_EXCL_START
1341d102b48SJeremy L Thompson       return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
135c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
1365fe0d4faSjeremylt 
1377509a596Sjeremylt     ierr = CeedElemRestrictionCreateStrided(delegate, nelem, elemsize, nnodes,
1387509a596Sjeremylt                                             ncomp, strides, rstr); CeedChk(ierr);
1395fe0d4faSjeremylt     return 0;
1405fe0d4faSjeremylt   }
1415fe0d4faSjeremylt 
1424ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
1434ce2993fSjeremylt   (*rstr)->ceed = ceed;
144d7b241e6Sjeremylt   ceed->refcount++;
1454ce2993fSjeremylt   (*rstr)->refcount = 1;
1464ce2993fSjeremylt   (*rstr)->nelem = nelem;
1474ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
1488795c945Sjeremylt   (*rstr)->nnodes = nnodes;
1494ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
1504ce2993fSjeremylt   (*rstr)->nblk = nelem;
1514ce2993fSjeremylt   (*rstr)->blksize = 1;
1527509a596Sjeremylt   ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr);
1537509a596Sjeremylt   for (int i = 0; i<3; i++)
1547509a596Sjeremylt     (*rstr)->strides[i] = strides[i];
1551dfeef1dSjeremylt   ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL,
1561dfeef1dSjeremylt                                      *rstr);
1574b8bea3bSJed Brown   CeedChk(ierr);
158d7b241e6Sjeremylt   return 0;
159d7b241e6Sjeremylt }
160d7b241e6Sjeremylt 
161d7b241e6Sjeremylt /**
162b11c1e72Sjeremylt   @brief Permute and pad indices for a blocked restriction
163d7b241e6Sjeremylt 
1648795c945Sjeremylt   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
1658795c945Sjeremylt                       ordered list of the indices (into the input CeedVector)
1668795c945Sjeremylt                       for the unknowns corresponding to element i, where
16734138859Sjeremylt                       0 <= i < @a nelem. All indices must be in the range
1688795c945Sjeremylt                       [0, @a nnodes).
169ecf6354eSJed Brown   @param blkindices Array of permuted and padded indices of
170ecf6354eSJed Brown                       shape [@a nblk, @a elemsize, @a blksize].
171d7b241e6Sjeremylt   @param nblk       Number of blocks
172d7b241e6Sjeremylt   @param nelem      Number of elements
173d7b241e6Sjeremylt   @param blksize    Number of elements in a block
174d7b241e6Sjeremylt   @param elemsize   Size of each element
175d7b241e6Sjeremylt 
176b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
177b11c1e72Sjeremylt 
178dfdf5a53Sjeremylt   @ref Utility
179b11c1e72Sjeremylt **/
180dfdf5a53Sjeremylt int CeedPermutePadIndices(const CeedInt *indices, CeedInt *blkindices,
181692c2638Sjeremylt                           CeedInt nblk, CeedInt nelem, CeedInt blksize,
182692c2638Sjeremylt                           CeedInt elemsize) {
183d7b241e6Sjeremylt   for (CeedInt e = 0; e < nblk*blksize; e+=blksize)
184d7b241e6Sjeremylt     for (int j = 0; j < blksize; j++)
185d7b241e6Sjeremylt       for (int k = 0; k < elemsize; k++)
186d7b241e6Sjeremylt         blkindices[e*elemsize + k*blksize + j]
187d7b241e6Sjeremylt           = indices[CeedIntMin(e+j,nelem-1)*elemsize + k];
188dfdf5a53Sjeremylt   return 0;
189d7b241e6Sjeremylt }
190d7b241e6Sjeremylt 
191d7b241e6Sjeremylt /**
192b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
193d7b241e6Sjeremylt 
194d7b241e6Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created.
19561dbc9d2Sjeremylt   @param imode      Ordering of the ncomp components, i.e. it specifies
196a8d32208Sjeremylt                       the ordering of the components of the L-vector used
19761dbc9d2Sjeremylt                       by this CeedElemRestriction. CEED_NONINTERLACED indicates
19861dbc9d2Sjeremylt                       the component is the outermost index and CEED_INTERLACED
199a8d32208Sjeremylt                       indicates the component is the innermost index in
200a8d32208Sjeremylt                       ordering of the L-vector.
201d7b241e6Sjeremylt   @param nelem      Number of elements described in the @a indices array.
202b11c1e72Sjeremylt   @param elemsize   Size (number of unknowns) per element
203b11c1e72Sjeremylt   @param blksize    Number of elements in a block
2048795c945Sjeremylt   @param nnodes     The number of nodes in the L-vector. The input CeedVector
2058795c945Sjeremylt                       to which the restriction will be applied is of size
2068795c945Sjeremylt                       @a nnodes * @a ncomp. This size may include data
207d7b241e6Sjeremylt                       used by other CeedElemRestriction objects describing
208d7b241e6Sjeremylt                       different types of elements.
20995bb1877Svaleriabarra   @param ncomp      Number of field components per interpolation node
21095bb1877Svaleriabarra                       (1 for scalar fields)
211b11c1e72Sjeremylt   @param mtype      Memory type of the @a indices array, see CeedMemType
212b11c1e72Sjeremylt   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
2138795c945Sjeremylt   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
2148795c945Sjeremylt                       ordered list of the indices (into the input CeedVector)
2158795c945Sjeremylt                       for the unknowns corresponding to element i, where
21634138859Sjeremylt                       0 <= i < @a nelem. All indices must be in the range
2178795c945Sjeremylt                       [0, @a nnodes). The backend will permute and pad this
2188795c945Sjeremylt                       array to the desired ordering for the blocksize, which is
2198795c945Sjeremylt                       typically given by the backend. The default reordering is
2208795c945Sjeremylt                       to interlace elements.
2214ce2993fSjeremylt   @param rstr       Address of the variable where the newly created
222b11c1e72Sjeremylt                       CeedElemRestriction will be stored
223d7b241e6Sjeremylt 
224b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
225dfdf5a53Sjeremylt 
226dfdf5a53Sjeremylt   @ref Advanced
227b11c1e72Sjeremylt  **/
22861dbc9d2Sjeremylt int CeedElemRestrictionCreateBlocked(Ceed ceed,  CeedInterlaceMode imode,
229a8d32208Sjeremylt                                      CeedInt nelem, CeedInt elemsize,
2308795c945Sjeremylt                                      CeedInt blksize, CeedInt nnodes,
2318795c945Sjeremylt                                      CeedInt ncomp, CeedMemType mtype,
2328795c945Sjeremylt                                      CeedCopyMode cmode, const CeedInt *indices,
2334ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
234d7b241e6Sjeremylt   int ierr;
235d7b241e6Sjeremylt   CeedInt *blkindices;
236d7b241e6Sjeremylt   CeedInt nblk = (nelem / blksize) + !!(nelem % blksize);
237d7b241e6Sjeremylt 
2385fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
2395fe0d4faSjeremylt     Ceed delegate;
240aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
241aefd8378Sjeremylt     CeedChk(ierr);
2425fe0d4faSjeremylt 
2435fe0d4faSjeremylt     if (!delegate)
244c042f62fSJeremy L Thompson       // LCOV_EXCL_START
2451d102b48SJeremy L Thompson       return CeedError(ceed, 1, "Backend does not support "
2461d102b48SJeremy L Thompson                        "ElemRestrictionCreateBlocked");
247c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
2485fe0d4faSjeremylt 
24961dbc9d2Sjeremylt     ierr = CeedElemRestrictionCreateBlocked(delegate, imode, nelem, elemsize,
2508795c945Sjeremylt                                             blksize, nnodes, ncomp, mtype, cmode,
2514ce2993fSjeremylt                                             indices, rstr); CeedChk(ierr);
2525fe0d4faSjeremylt     return 0;
2535fe0d4faSjeremylt   }
254d7b241e6Sjeremylt 
2554ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
256d7b241e6Sjeremylt 
257de686571SJeremy L Thompson   ierr = CeedCalloc(nblk*blksize*elemsize, &blkindices); CeedChk(ierr);
2584b8bea3bSJed Brown   ierr = CeedPermutePadIndices(indices, blkindices, nblk, nelem, blksize,
2594b8bea3bSJed Brown                                elemsize);
260dfdf5a53Sjeremylt   CeedChk(ierr);
261d7b241e6Sjeremylt 
2624ce2993fSjeremylt   (*rstr)->ceed = ceed;
263d7b241e6Sjeremylt   ceed->refcount++;
2644ce2993fSjeremylt   (*rstr)->refcount = 1;
26561dbc9d2Sjeremylt   (*rstr)->imode = imode;
2664ce2993fSjeremylt   (*rstr)->nelem = nelem;
2674ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
2688795c945Sjeremylt   (*rstr)->nnodes = nnodes;
2694ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
2704ce2993fSjeremylt   (*rstr)->nblk = nblk;
2714ce2993fSjeremylt   (*rstr)->blksize = blksize;
272667bc5fcSjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
2737f823360Sjeremylt          (const CeedInt *) blkindices, *rstr); CeedChk(ierr);
274d7b241e6Sjeremylt 
2751d102b48SJeremy L Thompson   if (cmode == CEED_OWN_POINTER) {
276d7b241e6Sjeremylt     ierr = CeedFree(&indices); CeedChk(ierr);
2771d102b48SJeremy L Thompson   }
278d7b241e6Sjeremylt 
279d7b241e6Sjeremylt   return 0;
280d7b241e6Sjeremylt }
281d7b241e6Sjeremylt 
282b11c1e72Sjeremylt /**
2837509a596Sjeremylt   @brief Create a blocked strided CeedElemRestriction
2847509a596Sjeremylt 
2857509a596Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
2867509a596Sjeremylt   @param nelem      Number of elements described by the restriction
2877509a596Sjeremylt   @param elemsize   Size (number of "nodes") per element
2887509a596Sjeremylt   @param blksize    Number of elements in a block
2897509a596Sjeremylt   @param nnodes     The number of nodes in the L-vector. The input CeedVector
2907509a596Sjeremylt                       to which the restriction will be applied is of size
2917509a596Sjeremylt                       @a nnodes * @a ncomp. This size may include data
2927509a596Sjeremylt                       used by other CeedElemRestriction objects describing
2937509a596Sjeremylt                       different types of elements.
2947509a596Sjeremylt   @param ncomp      Number of field components per interpolation node
2957509a596Sjeremylt                       (1 for scalar fields)
2967509a596Sjeremylt   @param strides    Array for strides between [nodes, components, elements].
2977509a596Sjeremylt                       The data for node i, component j, element k in the
2987509a596Sjeremylt                       L-vector is given by
2997509a596Sjeremylt                         i*strides[0] + j*strides[1] + k*strides[2]
3007509a596Sjeremylt   @param rstr       Address of the variable where the newly created
3017509a596Sjeremylt                       CeedElemRestriction will be stored
3027509a596Sjeremylt 
3037509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
3047509a596Sjeremylt 
3057509a596Sjeremylt   @ref Basic
3067509a596Sjeremylt **/
3077509a596Sjeremylt int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt nelem,
3087509a596Sjeremylt     CeedInt elemsize, CeedInt blksize,
3097509a596Sjeremylt     CeedInt nnodes, CeedInt ncomp,
3107509a596Sjeremylt     CeedInt strides[3],
3117509a596Sjeremylt     CeedElemRestriction *rstr) {
3127509a596Sjeremylt   int ierr;
3137509a596Sjeremylt   CeedInt nblk = (nelem / blksize) + !!(nelem % blksize);
3147509a596Sjeremylt 
3157509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
3167509a596Sjeremylt     Ceed delegate;
3177509a596Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
3187509a596Sjeremylt     CeedChk(ierr);
3197509a596Sjeremylt 
3207509a596Sjeremylt     if (!delegate)
3217509a596Sjeremylt       // LCOV_EXCL_START
3227509a596Sjeremylt       return CeedError(ceed, 1, "Backend does not support "
3237509a596Sjeremylt                        "ElemRestrictionCreateBlocked");
3247509a596Sjeremylt     // LCOV_EXCL_STOP
3257509a596Sjeremylt 
3267509a596Sjeremylt     ierr = CeedElemRestrictionCreateBlockedStrided(delegate, nelem, elemsize,
3277509a596Sjeremylt            blksize, nnodes, ncomp,
3287509a596Sjeremylt            strides, rstr);
3297509a596Sjeremylt     CeedChk(ierr);
3307509a596Sjeremylt     return 0;
3317509a596Sjeremylt   }
3327509a596Sjeremylt 
3337509a596Sjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
3347509a596Sjeremylt 
3357509a596Sjeremylt   (*rstr)->ceed = ceed;
3367509a596Sjeremylt   ceed->refcount++;
3377509a596Sjeremylt   (*rstr)->refcount = 1;
3387509a596Sjeremylt   (*rstr)->nelem = nelem;
3397509a596Sjeremylt   (*rstr)->elemsize = elemsize;
3407509a596Sjeremylt   (*rstr)->nnodes = nnodes;
3417509a596Sjeremylt   (*rstr)->ncomp = ncomp;
3427509a596Sjeremylt   (*rstr)->nblk = nblk;
3437509a596Sjeremylt   (*rstr)->blksize = blksize;
3447509a596Sjeremylt   ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr);
3457509a596Sjeremylt   for (int i = 0; i<3; i++)
3467509a596Sjeremylt     (*rstr)->strides[i] = strides[i];
3477509a596Sjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
3487509a596Sjeremylt          NULL, *rstr); CeedChk(ierr);
3497509a596Sjeremylt 
3507509a596Sjeremylt   return 0;
3517509a596Sjeremylt }
3527509a596Sjeremylt 
3537509a596Sjeremylt /**
354b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
355b11c1e72Sjeremylt 
3564ce2993fSjeremylt   @param rstr  CeedElemRestriction
357b11c1e72Sjeremylt   @param lvec  The address of the L-vector to be created, or NULL
358b11c1e72Sjeremylt   @param evec  The address of the E-vector to be created, or NULL
359b11c1e72Sjeremylt 
360b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
361dfdf5a53Sjeremylt 
362dfdf5a53Sjeremylt   @ref Advanced
363b11c1e72Sjeremylt **/
3644ce2993fSjeremylt int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *lvec,
365d7b241e6Sjeremylt                                     CeedVector *evec) {
366d7b241e6Sjeremylt   int ierr;
367d7b241e6Sjeremylt   CeedInt n, m;
3688795c945Sjeremylt   m = rstr->nnodes * rstr->ncomp;
3694ce2993fSjeremylt   n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
370d7b241e6Sjeremylt   if (lvec) {
3714ce2993fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, m, lvec); CeedChk(ierr);
372d7b241e6Sjeremylt   }
373d7b241e6Sjeremylt   if (evec) {
3744ce2993fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, n, evec); CeedChk(ierr);
375d7b241e6Sjeremylt   }
376d7b241e6Sjeremylt   return 0;
377d7b241e6Sjeremylt }
378d7b241e6Sjeremylt 
379d7b241e6Sjeremylt /**
380d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
381d7b241e6Sjeremylt 
3824ce2993fSjeremylt   @param rstr    CeedElemRestriction
383d7b241e6Sjeremylt   @param tmode   Apply restriction or transpose
3847aaeacdcSjeremylt   @param u       Input vector (of shape [@a nnodes, @a ncomp] when
38561dbc9d2Sjeremylt                    tmode=CEED_NOTRANSPOSE, imode=CEED_INTERLACED)
386a8d32208Sjeremylt   @param ru      Output vector (of shape [@a nelem * @a elemsize] when
3877aaeacdcSjeremylt                    tmode=CEED_NOTRANSPOSE). Ordering of the e-vector is decided
3887aaeacdcSjeremylt                    by the backend.
389d7b241e6Sjeremylt   @param request Request or CEED_REQUEST_IMMEDIATE
390b11c1e72Sjeremylt 
391b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
392dfdf5a53Sjeremylt 
393dfdf5a53Sjeremylt   @ref Advanced
394b11c1e72Sjeremylt **/
3954ce2993fSjeremylt int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode tmode,
396a8d32208Sjeremylt                              CeedVector u, CeedVector ru,
397a8d32208Sjeremylt                              CeedRequest *request) {
398d7b241e6Sjeremylt   CeedInt m,n;
399d7b241e6Sjeremylt   int ierr;
400d7b241e6Sjeremylt 
401d7b241e6Sjeremylt   if (tmode == CEED_NOTRANSPOSE) {
4024ce2993fSjeremylt     m = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
4038795c945Sjeremylt     n = rstr->nnodes * rstr->ncomp;
404d7b241e6Sjeremylt   } else {
4058795c945Sjeremylt     m = rstr->nnodes * rstr->ncomp;
4064ce2993fSjeremylt     n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
407d7b241e6Sjeremylt   }
408d7b241e6Sjeremylt   if (n != u->length)
409c042f62fSJeremy L Thompson     // LCOV_EXCL_START
4101d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Input vector size %d not compatible with "
4111d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
412c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
413a8d32208Sjeremylt   if (m != ru->length)
414c042f62fSJeremy L Thompson     // LCOV_EXCL_START
4151d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Output vector size %d not compatible with "
416a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
417c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
418074cb416Sjeremylt   ierr = rstr->Apply(rstr, tmode, u, ru, request); CeedChk(ierr);
419d7b241e6Sjeremylt 
420d7b241e6Sjeremylt   return 0;
421d7b241e6Sjeremylt }
422d7b241e6Sjeremylt 
423d7b241e6Sjeremylt /**
424d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
425be9261b7Sjeremylt 
426be9261b7Sjeremylt   @param rstr    CeedElemRestriction
4271f37b403Sjeremylt   @param block   Block number to restrict to/from, i.e. block=0 will handle
4281f37b403Sjeremylt                    elements [0 : blksize] and block=3 will handle elements
4291f37b403Sjeremylt                    [3*blksize : 4*blksize]
430be9261b7Sjeremylt   @param tmode   Apply restriction or transpose
4317aaeacdcSjeremylt   @param u       Input vector (of shape [@a nnodes, @a ncomp] when
43261dbc9d2Sjeremylt                    tmode=CEED_NOTRANSPOSE, imode=CEED_INTERLACED)
433a8d32208Sjeremylt   @param ru      Output vector (of shape [@a blksize * @a elemsize] when
4347aaeacdcSjeremylt                    tmode=CEED_NOTRANSPOSE). Ordering of the e-vector is decided
4357aaeacdcSjeremylt                    by the backend.
436be9261b7Sjeremylt   @param request Request or CEED_REQUEST_IMMEDIATE
437be9261b7Sjeremylt 
438be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
439be9261b7Sjeremylt 
440be9261b7Sjeremylt   @ref Advanced
441be9261b7Sjeremylt **/
442be9261b7Sjeremylt int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block,
443a8d32208Sjeremylt                                   CeedTransposeMode tmode, CeedVector u,
444a8d32208Sjeremylt                                   CeedVector ru, CeedRequest *request) {
445be9261b7Sjeremylt   CeedInt m,n;
446be9261b7Sjeremylt   int ierr;
447be9261b7Sjeremylt 
448be9261b7Sjeremylt   if (tmode == CEED_NOTRANSPOSE) {
449be9261b7Sjeremylt     m = rstr->blksize * rstr->elemsize * rstr->ncomp;
4508795c945Sjeremylt     n = rstr->nnodes * rstr->ncomp;
451be9261b7Sjeremylt   } else {
4528795c945Sjeremylt     m = rstr->nnodes * rstr->ncomp;
453be9261b7Sjeremylt     n = rstr->blksize * rstr->elemsize * rstr->ncomp;
454be9261b7Sjeremylt   }
455be9261b7Sjeremylt   if (n != u->length)
456c042f62fSJeremy L Thompson     // LCOV_EXCL_START
4571d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Input vector size %d not compatible with "
4581d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
459c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
460a8d32208Sjeremylt   if (m != ru->length)
461c042f62fSJeremy L Thompson     // LCOV_EXCL_START
4621d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Output vector size %d not compatible with "
463a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
464c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
465be9261b7Sjeremylt   if (rstr->blksize*block > rstr->nelem)
466c042f62fSJeremy L Thompson     // LCOV_EXCL_START
4671d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Cannot retrieve block %d, element %d > "
4681d102b48SJeremy L Thompson                      "total elements %d", block, rstr->blksize*block,
4691d102b48SJeremy L Thompson                      rstr->nelem);
470c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
471074cb416Sjeremylt   ierr = rstr->ApplyBlock(rstr, block, tmode, u, ru, request);
472be9261b7Sjeremylt   CeedChk(ierr);
473be9261b7Sjeremylt 
474be9261b7Sjeremylt   return 0;
475be9261b7Sjeremylt }
476be9261b7Sjeremylt 
477be9261b7Sjeremylt /**
478d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
4791469ee4dSjeremylt 
4801469ee4dSjeremylt   @param rstr             CeedElemRestriction
481b9c05c73SJed Brown   @param[out] mult        Vector to store multiplicity (of size nnodes*ncomp)
4821469ee4dSjeremylt 
4831469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
4841469ee4dSjeremylt 
4851469ee4dSjeremylt   @ref Advanced
4861469ee4dSjeremylt **/
4871469ee4dSjeremylt int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr,
4881469ee4dSjeremylt                                        CeedVector mult) {
4891469ee4dSjeremylt   int ierr;
4901469ee4dSjeremylt   CeedVector evec;
4911469ee4dSjeremylt 
4921469ee4dSjeremylt   // Create and set evec
4931469ee4dSjeremylt   ierr = CeedElemRestrictionCreateVector(rstr, NULL, &evec); CeedChk(ierr);
4941469ee4dSjeremylt   ierr = CeedVectorSetValue(evec, 1.0); CeedChk(ierr);
495fa9eac48SJed Brown   ierr = CeedVectorSetValue(mult, 0.0); CeedChk(ierr);
4961469ee4dSjeremylt 
4971469ee4dSjeremylt   // Apply to get multiplicity
498a8d32208Sjeremylt   ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, evec, mult,
499efc78312Sjeremylt                                   CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
5001469ee4dSjeremylt 
5011469ee4dSjeremylt   // Cleanup
5021469ee4dSjeremylt   ierr = CeedVectorDestroy(&evec); CeedChk(ierr);
5031469ee4dSjeremylt 
5041469ee4dSjeremylt   return 0;
5051469ee4dSjeremylt }
5061469ee4dSjeremylt 
5071469ee4dSjeremylt /**
5084ce2993fSjeremylt   @brief Get the Ceed associated with a CeedElemRestriction
5094ce2993fSjeremylt 
5104ce2993fSjeremylt   @param rstr             CeedElemRestriction
5114ce2993fSjeremylt   @param[out] ceed        Variable to store Ceed
5124ce2993fSjeremylt 
5134ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5144ce2993fSjeremylt 
51523617272Sjeremylt   @ref Advanced
5164ce2993fSjeremylt **/
5174ce2993fSjeremylt int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
5184ce2993fSjeremylt   *ceed = rstr->ceed;
5194ce2993fSjeremylt   return 0;
5204ce2993fSjeremylt }
5214ce2993fSjeremylt 
5224ce2993fSjeremylt /**
52361dbc9d2Sjeremylt   @brief Get the L-vector interlaced mode of a CeedElemRestriction
524a8d32208Sjeremylt 
525a8d32208Sjeremylt   @param rstr             CeedElemRestriction
52661dbc9d2Sjeremylt   @param[out] imode       Variable to store imode
527a8d32208Sjeremylt 
528a8d32208Sjeremylt   @return An error code: 0 - success, otherwise - failure
529a8d32208Sjeremylt 
530a8d32208Sjeremylt   @ref Advanced
531a8d32208Sjeremylt **/
53261dbc9d2Sjeremylt int CeedElemRestrictionGetIMode(CeedElemRestriction rstr,
53361dbc9d2Sjeremylt                                 CeedInterlaceMode *imode) {
5347509a596Sjeremylt   if (rstr->strides)
5357509a596Sjeremylt     // LCOV_EXCL_START
5367509a596Sjeremylt     return CeedError(rstr->ceed, 1, "Strided ElemRestriction has no interlace "
5377509a596Sjeremylt                      "mode");
5387509a596Sjeremylt   // LCOV_EXCL_STOP
5397509a596Sjeremylt 
54061dbc9d2Sjeremylt   *imode = rstr->imode;
541a8d32208Sjeremylt   return 0;
542a8d32208Sjeremylt }
543a8d32208Sjeremylt 
544a8d32208Sjeremylt /**
545b11c1e72Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
546d7b241e6Sjeremylt 
5474ce2993fSjeremylt   @param rstr             CeedElemRestriction
548288c0443SJeremy L Thompson   @param[out] numelem     Variable to store number of elements
549b11c1e72Sjeremylt 
550b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
551dfdf5a53Sjeremylt 
55223617272Sjeremylt   @ref Advanced
553b11c1e72Sjeremylt **/
5544ce2993fSjeremylt int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
5554ce2993fSjeremylt                                       CeedInt *numelem) {
5564ce2993fSjeremylt   *numelem = rstr->nelem;
5574ce2993fSjeremylt   return 0;
5584ce2993fSjeremylt }
5594ce2993fSjeremylt 
5604ce2993fSjeremylt /**
5614ce2993fSjeremylt   @brief Get the size of elements in the CeedElemRestriction
5624ce2993fSjeremylt 
5634ce2993fSjeremylt   @param rstr             CeedElemRestriction
5644ce2993fSjeremylt   @param[out] elemsize    Variable to store size of elements
5654ce2993fSjeremylt 
5664ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5674ce2993fSjeremylt 
56823617272Sjeremylt   @ref Advanced
5694ce2993fSjeremylt **/
5704ce2993fSjeremylt int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
5714ce2993fSjeremylt                                       CeedInt *elemsize) {
5724ce2993fSjeremylt   *elemsize = rstr->elemsize;
5734ce2993fSjeremylt   return 0;
5744ce2993fSjeremylt }
5754ce2993fSjeremylt 
5764ce2993fSjeremylt /**
5774ce2993fSjeremylt   @brief Get the number of degrees of freedom in the range of a
5784ce2993fSjeremylt          CeedElemRestriction
5794ce2993fSjeremylt 
5804ce2993fSjeremylt   @param rstr             CeedElemRestriction
5818795c945Sjeremylt   @param[out] numnodes    Variable to store number of nodes
5824ce2993fSjeremylt 
5834ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5844ce2993fSjeremylt 
58523617272Sjeremylt   @ref Advanced
5864ce2993fSjeremylt **/
5878795c945Sjeremylt int CeedElemRestrictionGetNumNodes(CeedElemRestriction rstr,
5888795c945Sjeremylt                                    CeedInt *numnodes) {
5898795c945Sjeremylt   *numnodes = rstr->nnodes;
5904ce2993fSjeremylt   return 0;
5914ce2993fSjeremylt }
5924ce2993fSjeremylt 
5934ce2993fSjeremylt /**
5944ce2993fSjeremylt   @brief Get the number of components in the elements of a
5954ce2993fSjeremylt          CeedElemRestriction
5964ce2993fSjeremylt 
5974ce2993fSjeremylt   @param rstr             CeedElemRestriction
5984ce2993fSjeremylt   @param[out] numcomp     Variable to store number of components
5994ce2993fSjeremylt 
6004ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
6014ce2993fSjeremylt 
60223617272Sjeremylt   @ref Advanced
6034ce2993fSjeremylt **/
6044ce2993fSjeremylt int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
6054ce2993fSjeremylt                                         CeedInt *numcomp) {
6064ce2993fSjeremylt   *numcomp = rstr->ncomp;
6074ce2993fSjeremylt   return 0;
6084ce2993fSjeremylt }
6094ce2993fSjeremylt 
6104ce2993fSjeremylt /**
6114ce2993fSjeremylt   @brief Get the number of blocks in a CeedElemRestriction
6124ce2993fSjeremylt 
6134ce2993fSjeremylt   @param rstr             CeedElemRestriction
6144ce2993fSjeremylt   @param[out] numblock    Variable to store number of blocks
6154ce2993fSjeremylt 
6164ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
6174ce2993fSjeremylt 
61823617272Sjeremylt   @ref Advanced
6194ce2993fSjeremylt **/
6204ce2993fSjeremylt int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
6214ce2993fSjeremylt                                     CeedInt *numblock) {
6224ce2993fSjeremylt   *numblock = rstr->nblk;
6234ce2993fSjeremylt   return 0;
6244ce2993fSjeremylt }
6254ce2993fSjeremylt 
6264ce2993fSjeremylt /**
6274ce2993fSjeremylt   @brief Get the size of blocks in the CeedElemRestriction
6284ce2993fSjeremylt 
629288c0443SJeremy L Thompson   @param rstr             CeedElemRestriction
6304ce2993fSjeremylt   @param[out] blksize     Variable to store size of blocks
6314ce2993fSjeremylt 
6324ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
6334ce2993fSjeremylt 
63423617272Sjeremylt   @ref Advanced
6354ce2993fSjeremylt **/
6364ce2993fSjeremylt int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
6374ce2993fSjeremylt                                     CeedInt *blksize) {
6384ce2993fSjeremylt   *blksize = rstr->blksize;
6394ce2993fSjeremylt   return 0;
6404ce2993fSjeremylt }
6414ce2993fSjeremylt 
6424ce2993fSjeremylt /**
6437509a596Sjeremylt   @brief Get the strides of a strided CeedElemRestriction
6447509a596Sjeremylt 
6457509a596Sjeremylt   @param rstr             CeedElemRestriction
6467509a596Sjeremylt   @param[out] strides     Variable to store strides array
6477509a596Sjeremylt 
6487509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
6497509a596Sjeremylt 
6507509a596Sjeremylt   @ref Advanced
6517509a596Sjeremylt **/
6527509a596Sjeremylt int CeedElemRestrictionGetStrides(CeedElemRestriction rstr,
6537509a596Sjeremylt                                   CeedInt (*strides)[3]) {
6547509a596Sjeremylt   if (!rstr->strides)
6557509a596Sjeremylt     // LCOV_EXCL_START
6567509a596Sjeremylt     return CeedError(rstr->ceed, 1, "ElemRestriction has no stride data");
6577509a596Sjeremylt   // LCOV_EXCL_STOP
6587509a596Sjeremylt 
6597509a596Sjeremylt   for (int i = 0; i<3; i++)
6607509a596Sjeremylt     (*strides)[i] = rstr->strides[i];
6617509a596Sjeremylt   return 0;
6627509a596Sjeremylt }
6637509a596Sjeremylt 
6647509a596Sjeremylt /**
6654ce2993fSjeremylt   @brief Get the backend data of a CeedElemRestriction
6664ce2993fSjeremylt 
667288c0443SJeremy L Thompson   @param rstr             CeedElemRestriction
6684ce2993fSjeremylt   @param[out] data        Variable to store data
6694ce2993fSjeremylt 
6704ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
6714ce2993fSjeremylt 
67223617272Sjeremylt   @ref Advanced
6734ce2993fSjeremylt **/
6741d102b48SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void **data) {
6754ce2993fSjeremylt   *data = rstr->data;
676d7b241e6Sjeremylt   return 0;
677d7b241e6Sjeremylt }
678d7b241e6Sjeremylt 
679d7b241e6Sjeremylt /**
680fe2413ffSjeremylt   @brief Set the backend data of a CeedElemRestriction
681fe2413ffSjeremylt 
682288c0443SJeremy L Thompson   @param[out] rstr        CeedElemRestriction
683fe2413ffSjeremylt   @param data             Data to set
684fe2413ffSjeremylt 
685fe2413ffSjeremylt   @return An error code: 0 - success, otherwise - failure
686fe2413ffSjeremylt 
687fe2413ffSjeremylt   @ref Advanced
688fe2413ffSjeremylt **/
6891d102b48SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void **data) {
690fe2413ffSjeremylt   rstr->data = *data;
691fe2413ffSjeremylt   return 0;
692fe2413ffSjeremylt }
693fe2413ffSjeremylt 
694fe2413ffSjeremylt /**
695f02ca4a2SJed Brown   @brief View a CeedElemRestriction
696f02ca4a2SJed Brown 
697f02ca4a2SJed Brown   @param[in] rstr    CeedElemRestriction to view
698f02ca4a2SJed Brown   @param[in] stream  Stream to write; typically stdout/stderr or a file
699f02ca4a2SJed Brown 
700f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
701f02ca4a2SJed Brown 
702f02ca4a2SJed Brown   @ref Utility
703f02ca4a2SJed Brown **/
704f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
7057509a596Sjeremylt   char stridesstr[500];
7067509a596Sjeremylt   if (rstr->strides)
7077509a596Sjeremylt     sprintf(stridesstr, "[%d, %d, %d]", rstr->strides[0], rstr->strides[1],
7087509a596Sjeremylt             rstr->strides[2]);
7097509a596Sjeremylt 
710*0036de2cSjeremylt   fprintf(stream, "%sCeedElemRestriction from (%d, %d) to %d elements with %d "
711*0036de2cSjeremylt           "nodes each and %s %s\n", rstr->blksize > 1 ? "Blocked " : "",
712*0036de2cSjeremylt           rstr->nnodes, rstr->ncomp, rstr->nelem, rstr->elemsize,
713*0036de2cSjeremylt           rstr->strides ? "strides" : "L-vector components",
7147509a596Sjeremylt           rstr->strides ? stridesstr : CeedInterlaceModes[rstr->imode]);
715f02ca4a2SJed Brown   return 0;
716f02ca4a2SJed Brown }
717f02ca4a2SJed Brown 
718f02ca4a2SJed Brown /**
719b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
720b11c1e72Sjeremylt 
7214ce2993fSjeremylt   @param rstr  CeedElemRestriction to destroy
722b11c1e72Sjeremylt 
723b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
724dfdf5a53Sjeremylt 
725dfdf5a53Sjeremylt   @ref Basic
726b11c1e72Sjeremylt **/
7274ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
728d7b241e6Sjeremylt   int ierr;
729d7b241e6Sjeremylt 
7301d102b48SJeremy L Thompson   if (!*rstr || --(*rstr)->refcount > 0)
7311d102b48SJeremy L Thompson     return 0;
7324ce2993fSjeremylt   if ((*rstr)->Destroy) {
7334ce2993fSjeremylt     ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr);
734d7b241e6Sjeremylt   }
7357509a596Sjeremylt   ierr = CeedFree(&(*rstr)->strides); CeedChk(ierr);
7364ce2993fSjeremylt   ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr);
7374ce2993fSjeremylt   ierr = CeedFree(rstr); CeedChk(ierr);
738d7b241e6Sjeremylt   return 0;
739d7b241e6Sjeremylt }
740d7b241e6Sjeremylt 
741d7b241e6Sjeremylt /// @}
742