xref: /libCEED/interface/ceed-elemrestriction.c (revision bd33150addfd586a5f97816a8026f45b5a27ec2c)
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 
207a982d89SJeremy L. Thompson /// @file
217a982d89SJeremy L. Thompson /// Implementation of CeedElemRestriction interfaces
227a982d89SJeremy L. Thompson 
237a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
247a982d89SJeremy L. Thompson /// CeedElemRestriction Library Internal Functions
257a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
267a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionDeveloper
277a982d89SJeremy L. Thompson /// @{
287a982d89SJeremy L. Thompson 
297a982d89SJeremy L. Thompson /**
30d979a051Sjeremylt   @brief Permute and pad offsets for a blocked restriction
317a982d89SJeremy L. Thompson 
32d979a051Sjeremylt   @param offsets    Array of shape [@a nelem, @a elemsize]. Row i holds the
33d979a051Sjeremylt                       ordered list of the offsets (into the input CeedVector)
347a982d89SJeremy L. Thompson                       for the unknowns corresponding to element i, where
35d979a051Sjeremylt                       0 <= i < @a nelem. All offsets must be in the range
36d979a051Sjeremylt                       [0, @a lsize - 1].
37d979a051Sjeremylt   @param blkoffsets Array of permuted and padded offsets of
387a982d89SJeremy L. Thompson                       shape [@a nblk, @a elemsize, @a blksize].
397a982d89SJeremy L. Thompson   @param nblk       Number of blocks
407a982d89SJeremy L. Thompson   @param nelem      Number of elements
417a982d89SJeremy L. Thompson   @param blksize    Number of elements in a block
427a982d89SJeremy L. Thompson   @param elemsize   Size of each element
437a982d89SJeremy L. Thompson 
447a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
457a982d89SJeremy L. Thompson 
467a982d89SJeremy L. Thompson   @ref Utility
477a982d89SJeremy L. Thompson **/
48d979a051Sjeremylt int CeedPermutePadOffsets(const CeedInt *offsets, CeedInt *blkoffsets,
497a982d89SJeremy L. Thompson                           CeedInt nblk, CeedInt nelem, CeedInt blksize,
507a982d89SJeremy L. Thompson                           CeedInt elemsize) {
517a982d89SJeremy L. Thompson   for (CeedInt e = 0; e < nblk*blksize; e+=blksize)
527a982d89SJeremy L. Thompson     for (int j = 0; j < blksize; j++)
537a982d89SJeremy L. Thompson       for (int k = 0; k < elemsize; k++)
54d979a051Sjeremylt         blkoffsets[e*elemsize + k*blksize + j]
55d979a051Sjeremylt           = offsets[CeedIntMin(e+j,nelem-1)*elemsize + k];
567a982d89SJeremy L. Thompson   return 0;
577a982d89SJeremy L. Thompson }
587a982d89SJeremy L. Thompson 
597a982d89SJeremy L. Thompson /// @}
607a982d89SJeremy L. Thompson 
617a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
627a982d89SJeremy L. Thompson /// CeedElemRestriction Backend API
637a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
647a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionBackend
657a982d89SJeremy L. Thompson /// @{
667a982d89SJeremy L. Thompson 
677a982d89SJeremy L. Thompson /**
687a982d89SJeremy L. Thompson   @brief Get the Ceed associated with a CeedElemRestriction
697a982d89SJeremy L. Thompson 
707a982d89SJeremy L. Thompson   @param rstr             CeedElemRestriction
717a982d89SJeremy L. Thompson   @param[out] ceed        Variable to store Ceed
727a982d89SJeremy L. Thompson 
737a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
747a982d89SJeremy L. Thompson 
757a982d89SJeremy L. Thompson   @ref Backend
767a982d89SJeremy L. Thompson **/
777a982d89SJeremy L. Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
787a982d89SJeremy L. Thompson   *ceed = rstr->ceed;
797a982d89SJeremy L. Thompson   return 0;
807a982d89SJeremy L. Thompson }
817a982d89SJeremy L. Thompson 
827a982d89SJeremy L. Thompson /**
83a681ae63Sjeremylt 
84a681ae63Sjeremylt   @brief Get the strides of a strided CeedElemRestriction
857a982d89SJeremy L. Thompson 
867a982d89SJeremy L. Thompson   @param rstr             CeedElemRestriction
87a681ae63Sjeremylt   @param[out] strides     Variable to store strides array
887a982d89SJeremy L. Thompson 
897a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
907a982d89SJeremy L. Thompson 
917a982d89SJeremy L. Thompson   @ref Backend
927a982d89SJeremy L. Thompson **/
93a681ae63Sjeremylt int CeedElemRestrictionGetStrides(CeedElemRestriction rstr,
94a681ae63Sjeremylt                                   CeedInt (*strides)[3]) {
95a681ae63Sjeremylt   if (!rstr->strides)
96a681ae63Sjeremylt     // LCOV_EXCL_START
97a681ae63Sjeremylt     return CeedError(rstr->ceed, 1, "ElemRestriction has no stride data");
98a681ae63Sjeremylt   // LCOV_EXCL_STOP
99a681ae63Sjeremylt 
100a681ae63Sjeremylt   for (int i = 0; i<3; i++)
101a681ae63Sjeremylt     (*strides)[i] = rstr->strides[i];
1027a982d89SJeremy L. Thompson   return 0;
1037a982d89SJeremy L. Thompson }
1047a982d89SJeremy L. Thompson 
1057a982d89SJeremy L. Thompson /**
106*bd33150aSjeremylt   @brief Get read-only access to a CeedElemRestriction offsets array by memtype
107*bd33150aSjeremylt 
108*bd33150aSjeremylt   @param rstr         CeedElemRestriction to retrieve offsets
109*bd33150aSjeremylt   @param mtype        Memory type on which to access the array.  If the backend
110*bd33150aSjeremylt                         uses a different memory type, this will perform a copy
111*bd33150aSjeremylt                         (possibly cached).
112*bd33150aSjeremylt   @param[out] offsets Array on memory type mtype
113*bd33150aSjeremylt 
114*bd33150aSjeremylt   @return An error code: 0 - success, otherwise - failure
115*bd33150aSjeremylt 
116*bd33150aSjeremylt   @ref User
117*bd33150aSjeremylt **/
118*bd33150aSjeremylt int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, CeedMemType mtype,
119*bd33150aSjeremylt                                   const CeedInt **offsets) {
120*bd33150aSjeremylt   int ierr;
121*bd33150aSjeremylt 
122*bd33150aSjeremylt   if (!rstr->GetOffsets)
123*bd33150aSjeremylt     // LCOV_EXCL_START
124*bd33150aSjeremylt     return CeedError(rstr->ceed, 1, "Backend does not support GetOffsets");
125*bd33150aSjeremylt   // LCOV_EXCL_STOP
126*bd33150aSjeremylt 
127*bd33150aSjeremylt   ierr = rstr->GetOffsets(rstr, mtype, offsets); CeedChk(ierr);
128*bd33150aSjeremylt   return 0;
129*bd33150aSjeremylt }
130*bd33150aSjeremylt 
131*bd33150aSjeremylt /**
132a681ae63Sjeremylt   @brief Get the backend stride status of a CeedElemRestriction
1337a982d89SJeremy L. Thompson 
1347a982d89SJeremy L. Thompson   @param rstr             CeedElemRestriction
135a681ae63Sjeremylt   @param[out] status      Variable to store stride status
1367a982d89SJeremy L. Thompson 
1377a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1387a982d89SJeremy L. Thompson 
1397a982d89SJeremy L. Thompson   @ref Backend
1407a982d89SJeremy L. Thompson **/
141a681ae63Sjeremylt int CeedElemRestrictionGetBackendStridesStatus(CeedElemRestriction rstr,
142a681ae63Sjeremylt     bool *status) {
143a681ae63Sjeremylt   if (!rstr->strides)
144a681ae63Sjeremylt     // LCOV_EXCL_START
145a681ae63Sjeremylt     return CeedError(rstr->ceed, 1, "ElemRestriction has no stride data");
146a681ae63Sjeremylt   // LCOV_EXCL_STOP
1477a982d89SJeremy L. Thompson 
148a681ae63Sjeremylt   *status = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) &&
149a681ae63Sjeremylt              (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
150a681ae63Sjeremylt              (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
1517a982d89SJeremy L. Thompson   return 0;
1527a982d89SJeremy L. Thompson }
1537a982d89SJeremy L. Thompson 
1547a982d89SJeremy L. Thompson /**
1557a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedElemRestriction
1567a982d89SJeremy L. Thompson 
1577a982d89SJeremy L. Thompson   @param rstr             CeedElemRestriction
1587a982d89SJeremy L. Thompson   @param[out] data        Variable to store data
1597a982d89SJeremy L. Thompson 
1607a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1617a982d89SJeremy L. Thompson 
1627a982d89SJeremy L. Thompson   @ref Backend
1637a982d89SJeremy L. Thompson **/
1647a982d89SJeremy L. Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void **data) {
1657a982d89SJeremy L. Thompson   *data = rstr->data;
1667a982d89SJeremy L. Thompson   return 0;
1677a982d89SJeremy L. Thompson }
1687a982d89SJeremy L. Thompson 
1697a982d89SJeremy L. Thompson /**
1707a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedElemRestriction
1717a982d89SJeremy L. Thompson 
1727a982d89SJeremy L. Thompson   @param[out] rstr        CeedElemRestriction
1737a982d89SJeremy L. Thompson   @param data             Data to set
1747a982d89SJeremy L. Thompson 
1757a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1767a982d89SJeremy L. Thompson 
1777a982d89SJeremy L. Thompson   @ref Backend
1787a982d89SJeremy L. Thompson **/
1797a982d89SJeremy L. Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void **data) {
1807a982d89SJeremy L. Thompson   rstr->data = *data;
1817a982d89SJeremy L. Thompson   return 0;
1827a982d89SJeremy L. Thompson }
1837a982d89SJeremy L. Thompson 
1847a982d89SJeremy L. Thompson /// @}
1857a982d89SJeremy L. Thompson 
18615910d16Sjeremylt /// @cond DOXYGEN_SKIP
18715910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
18815910d16Sjeremylt /// @endcond
18915910d16Sjeremylt 
1907a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1917a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
1927a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1937a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
194d7b241e6Sjeremylt /// @{
195d7b241e6Sjeremylt 
1967a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
1977a982d89SJeremy L. Thompson const CeedInt CEED_STRIDES_BACKEND[3] = {};
1987a982d89SJeremy L. Thompson 
1997a982d89SJeremy L. Thompson /// Indicate that no ElemRestriction is provided by the user
2007a982d89SJeremy L. Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE =
2017a982d89SJeremy L. Thompson   &ceed_elemrestriction_none;
2027a982d89SJeremy L. Thompson 
203d7b241e6Sjeremylt /**
204b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
205d7b241e6Sjeremylt 
206b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
207d979a051Sjeremylt   @param nelem      Number of elements described in the @a offsets array
208b11c1e72Sjeremylt   @param elemsize   Size (number of "nodes") per element
209b11c1e72Sjeremylt   @param ncomp      Number of field components per interpolation node
21095bb1877Svaleriabarra                       (1 for scalar fields)
211d979a051Sjeremylt   @param compstride Stride between components for the same L-vector "node".
212d979a051Sjeremylt                       Data for node i, component k can be found in the L-vector
213d979a051Sjeremylt                       at index [offsets[i] + k*compstride].
214d979a051Sjeremylt   @param lsize      The size of the L-vector. This vector may be larger than
215d979a051Sjeremylt                       the elements and fields given by this restriction.
216d979a051Sjeremylt   @param mtype      Memory type of the @a offsets array, see CeedMemType
217d979a051Sjeremylt   @param cmode      Copy mode for the @a offsets array, see CeedCopyMode
218d979a051Sjeremylt   @param offsets    Array of shape [@a nelem, @a elemsize]. Row i holds the
219d979a051Sjeremylt                       ordered list of the offsets (into the input CeedVector)
2208795c945Sjeremylt                       for the unknowns corresponding to element i, where
221d979a051Sjeremylt                       0 <= i < @a nelem. All offsets must be in the range
222d979a051Sjeremylt                       [0, @a lsize - 1].
2234ce2993fSjeremylt   @param[out] rstr  Address of the variable where the newly created
224b11c1e72Sjeremylt                       CeedElemRestriction will be stored
225d7b241e6Sjeremylt 
226b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
227dfdf5a53Sjeremylt 
2287a982d89SJeremy L. Thompson   @ref User
229b11c1e72Sjeremylt **/
230d979a051Sjeremylt int CeedElemRestrictionCreate(Ceed ceed, CeedInt nelem, CeedInt elemsize,
231d979a051Sjeremylt                               CeedInt ncomp, CeedInt compstride,
232d979a051Sjeremylt                               CeedInt lsize, CeedMemType mtype,
233d979a051Sjeremylt                               CeedCopyMode cmode, const CeedInt *offsets,
2344ce2993fSjeremylt                               CeedElemRestriction *rstr) {
235d7b241e6Sjeremylt   int ierr;
236d7b241e6Sjeremylt 
2375fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
2385fe0d4faSjeremylt     Ceed delegate;
239aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
240aefd8378Sjeremylt     CeedChk(ierr);
2415fe0d4faSjeremylt 
2425fe0d4faSjeremylt     if (!delegate)
243c042f62fSJeremy L Thompson       // LCOV_EXCL_START
244d7b241e6Sjeremylt       return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
245c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
2465fe0d4faSjeremylt 
247d979a051Sjeremylt     ierr = CeedElemRestrictionCreate(delegate, nelem, elemsize, ncomp,
248d979a051Sjeremylt                                      compstride, lsize, mtype, cmode,
249d979a051Sjeremylt                                      offsets, rstr); CeedChk(ierr);
2505fe0d4faSjeremylt     return 0;
2515fe0d4faSjeremylt   }
2525fe0d4faSjeremylt 
2534ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
2544ce2993fSjeremylt   (*rstr)->ceed = ceed;
255d7b241e6Sjeremylt   ceed->refcount++;
2564ce2993fSjeremylt   (*rstr)->refcount = 1;
2574ce2993fSjeremylt   (*rstr)->nelem = nelem;
2584ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
2594ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
260d979a051Sjeremylt   (*rstr)->compstride = compstride;
261d979a051Sjeremylt   (*rstr)->lsize = lsize;
2624ce2993fSjeremylt   (*rstr)->nblk = nelem;
2634ce2993fSjeremylt   (*rstr)->blksize = 1;
264d979a051Sjeremylt   ierr = ceed->ElemRestrictionCreate(mtype, cmode, offsets, *rstr);
265d979a051Sjeremylt   CeedChk(ierr);
266d7b241e6Sjeremylt   return 0;
267d7b241e6Sjeremylt }
268d7b241e6Sjeremylt 
269d7b241e6Sjeremylt /**
2707509a596Sjeremylt   @brief Create a strided CeedElemRestriction
271d7b241e6Sjeremylt 
272b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
2737509a596Sjeremylt   @param nelem      Number of elements described by the restriction
274b11c1e72Sjeremylt   @param elemsize   Size (number of "nodes") per element
275b11c1e72Sjeremylt   @param ncomp      Number of field components per interpolation node
27695bb1877Svaleriabarra                       (1 for scalar fields)
277d979a051Sjeremylt   @param lsize      The size of the L-vector. This vector may be larger than
278d979a051Sjeremylt                       the elements and fields given by this restriction.
2797509a596Sjeremylt   @param strides    Array for strides between [nodes, components, elements].
2807509a596Sjeremylt                       The data for node i, component j, element k in the
2817509a596Sjeremylt                       L-vector is given by
2827509a596Sjeremylt                         i*strides[0] + j*strides[1] + k*strides[2]
2834ce2993fSjeremylt   @param rstr       Address of the variable where the newly created
284b11c1e72Sjeremylt                       CeedElemRestriction will be stored
285d7b241e6Sjeremylt 
286b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
287dfdf5a53Sjeremylt 
2887a982d89SJeremy L. Thompson   @ref User
289b11c1e72Sjeremylt **/
2907509a596Sjeremylt int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt nelem, CeedInt elemsize,
291d979a051Sjeremylt                                      CeedInt ncomp, CeedInt lsize,
2928621c6c6SJeremy L Thompson                                      const CeedInt strides[3],
293f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
294d7b241e6Sjeremylt   int ierr;
295d7b241e6Sjeremylt 
2965fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
2975fe0d4faSjeremylt     Ceed delegate;
298aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
299aefd8378Sjeremylt     CeedChk(ierr);
3005fe0d4faSjeremylt 
3015fe0d4faSjeremylt     if (!delegate)
302c042f62fSJeremy L Thompson       // LCOV_EXCL_START
3031d102b48SJeremy L Thompson       return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
304c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
3055fe0d4faSjeremylt 
306d979a051Sjeremylt     ierr = CeedElemRestrictionCreateStrided(delegate, nelem, elemsize, ncomp,
307d979a051Sjeremylt                                             lsize, strides, rstr);
308d979a051Sjeremylt     CeedChk(ierr);
3095fe0d4faSjeremylt     return 0;
3105fe0d4faSjeremylt   }
3115fe0d4faSjeremylt 
3124ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
3134ce2993fSjeremylt   (*rstr)->ceed = ceed;
314d7b241e6Sjeremylt   ceed->refcount++;
3154ce2993fSjeremylt   (*rstr)->refcount = 1;
3164ce2993fSjeremylt   (*rstr)->nelem = nelem;
3174ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
3184ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
319d979a051Sjeremylt   (*rstr)->lsize = lsize;
3204ce2993fSjeremylt   (*rstr)->nblk = nelem;
3214ce2993fSjeremylt   (*rstr)->blksize = 1;
3227509a596Sjeremylt   ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr);
3237509a596Sjeremylt   for (int i = 0; i<3; i++)
3247509a596Sjeremylt     (*rstr)->strides[i] = strides[i];
3251dfeef1dSjeremylt   ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL,
3261dfeef1dSjeremylt                                      *rstr);
3274b8bea3bSJed Brown   CeedChk(ierr);
328d7b241e6Sjeremylt   return 0;
329d7b241e6Sjeremylt }
330d7b241e6Sjeremylt 
331d7b241e6Sjeremylt /**
332b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
333d7b241e6Sjeremylt 
334d7b241e6Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created.
335d979a051Sjeremylt   @param nelem      Number of elements described in the @a offsets array.
336b11c1e72Sjeremylt   @param elemsize   Size (number of unknowns) per element
337b11c1e72Sjeremylt   @param blksize    Number of elements in a block
33895bb1877Svaleriabarra   @param ncomp      Number of field components per interpolation node
33995bb1877Svaleriabarra                       (1 for scalar fields)
340d979a051Sjeremylt   @param compstride Stride between components for the same L-vector "node".
341d979a051Sjeremylt                       Data for node i, component k can be found in the L-vector
342d979a051Sjeremylt                       at index [offsets[i] + k*compstride].
343d979a051Sjeremylt   @param lsize      The size of the L-vector. This vector may be larger than
344d979a051Sjeremylt                       the elements and fields given by this restriction.
345d979a051Sjeremylt   @param mtype      Memory type of the @a offsets array, see CeedMemType
346d979a051Sjeremylt   @param cmode      Copy mode for the @a offsets array, see CeedCopyMode
347d979a051Sjeremylt   @param offsets    Array of shape [@a nelem, @a elemsize]. Row i holds the
348d979a051Sjeremylt                       ordered list of the offsets (into the input CeedVector)
3498795c945Sjeremylt                       for the unknowns corresponding to element i, where
350d979a051Sjeremylt                       0 <= i < @a nelem. All offsets must be in the range
351d979a051Sjeremylt                       [0, @a lsize - 1]. The backend will permute and pad this
3528795c945Sjeremylt                       array to the desired ordering for the blocksize, which is
3538795c945Sjeremylt                       typically given by the backend. The default reordering is
3548795c945Sjeremylt                       to interlace elements.
3554ce2993fSjeremylt   @param rstr       Address of the variable where the newly created
356b11c1e72Sjeremylt                       CeedElemRestriction will be stored
357d7b241e6Sjeremylt 
358b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
359dfdf5a53Sjeremylt 
3607a982d89SJeremy L. Thompson   @ref Backend
361b11c1e72Sjeremylt  **/
362d979a051Sjeremylt int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt nelem, CeedInt elemsize,
363d979a051Sjeremylt                                      CeedInt blksize, CeedInt ncomp,
364d979a051Sjeremylt                                      CeedInt compstride, CeedInt lsize,
365d979a051Sjeremylt                                      CeedMemType mtype, CeedCopyMode cmode,
366d979a051Sjeremylt                                      const CeedInt *offsets,
3674ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
368d7b241e6Sjeremylt   int ierr;
369d979a051Sjeremylt   CeedInt *blkoffsets;
370d7b241e6Sjeremylt   CeedInt nblk = (nelem / blksize) + !!(nelem % blksize);
371d7b241e6Sjeremylt 
3725fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
3735fe0d4faSjeremylt     Ceed delegate;
374aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
375aefd8378Sjeremylt     CeedChk(ierr);
3765fe0d4faSjeremylt 
3775fe0d4faSjeremylt     if (!delegate)
378c042f62fSJeremy L Thompson       // LCOV_EXCL_START
3791d102b48SJeremy L Thompson       return CeedError(ceed, 1, "Backend does not support "
3801d102b48SJeremy L Thompson                        "ElemRestrictionCreateBlocked");
381c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
3825fe0d4faSjeremylt 
383d979a051Sjeremylt     ierr = CeedElemRestrictionCreateBlocked(delegate, nelem, elemsize, blksize,
384d979a051Sjeremylt                                             ncomp, compstride, lsize, mtype,
385d979a051Sjeremylt                                             cmode, offsets, rstr);
386d979a051Sjeremylt     CeedChk(ierr);
3875fe0d4faSjeremylt     return 0;
3885fe0d4faSjeremylt   }
389d7b241e6Sjeremylt 
3904ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
391d7b241e6Sjeremylt 
392d979a051Sjeremylt   ierr = CeedCalloc(nblk*blksize*elemsize, &blkoffsets); CeedChk(ierr);
393d979a051Sjeremylt   ierr = CeedPermutePadOffsets(offsets, blkoffsets, nblk, nelem, blksize,
3944b8bea3bSJed Brown                                elemsize);
395dfdf5a53Sjeremylt   CeedChk(ierr);
396d7b241e6Sjeremylt 
3974ce2993fSjeremylt   (*rstr)->ceed = ceed;
398d7b241e6Sjeremylt   ceed->refcount++;
3994ce2993fSjeremylt   (*rstr)->refcount = 1;
4004ce2993fSjeremylt   (*rstr)->nelem = nelem;
4014ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
4024ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
403d979a051Sjeremylt   (*rstr)->compstride = compstride;
404d979a051Sjeremylt   (*rstr)->lsize = lsize;
4054ce2993fSjeremylt   (*rstr)->nblk = nblk;
4064ce2993fSjeremylt   (*rstr)->blksize = blksize;
407667bc5fcSjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
408d979a051Sjeremylt          (const CeedInt *) blkoffsets, *rstr); CeedChk(ierr);
409d7b241e6Sjeremylt 
4101d102b48SJeremy L Thompson   if (cmode == CEED_OWN_POINTER) {
411d979a051Sjeremylt     ierr = CeedFree(&offsets); CeedChk(ierr);
4121d102b48SJeremy L Thompson   }
413d7b241e6Sjeremylt 
414d7b241e6Sjeremylt   return 0;
415d7b241e6Sjeremylt }
416d7b241e6Sjeremylt 
417b11c1e72Sjeremylt /**
4187509a596Sjeremylt   @brief Create a blocked strided CeedElemRestriction
4197509a596Sjeremylt 
4207509a596Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
4217509a596Sjeremylt   @param nelem      Number of elements described by the restriction
4227509a596Sjeremylt   @param elemsize   Size (number of "nodes") per element
4237509a596Sjeremylt   @param blksize    Number of elements in a block
4247509a596Sjeremylt   @param ncomp      Number of field components per interpolation node
4257509a596Sjeremylt                       (1 for scalar fields)
426d979a051Sjeremylt   @param lsize      The size of the L-vector. This vector may be larger than
427d979a051Sjeremylt                       the elements and fields given by this restriction.
4287509a596Sjeremylt   @param strides    Array for strides between [nodes, components, elements].
4297509a596Sjeremylt                       The data for node i, component j, element k in the
4307509a596Sjeremylt                       L-vector is given by
4317509a596Sjeremylt                         i*strides[0] + j*strides[1] + k*strides[2]
4327509a596Sjeremylt   @param rstr       Address of the variable where the newly created
4337509a596Sjeremylt                       CeedElemRestriction will be stored
4347509a596Sjeremylt 
4357509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
4367509a596Sjeremylt 
4377a982d89SJeremy L. Thompson   @ref User
4387509a596Sjeremylt **/
4397509a596Sjeremylt int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt nelem,
440d979a051Sjeremylt     CeedInt elemsize, CeedInt blksize, CeedInt ncomp, CeedInt lsize,
4418621c6c6SJeremy L Thompson     const CeedInt strides[3], CeedElemRestriction *rstr) {
4427509a596Sjeremylt   int ierr;
4437509a596Sjeremylt   CeedInt nblk = (nelem / blksize) + !!(nelem % blksize);
4447509a596Sjeremylt 
4457509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
4467509a596Sjeremylt     Ceed delegate;
4477509a596Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
4487509a596Sjeremylt     CeedChk(ierr);
4497509a596Sjeremylt 
4507509a596Sjeremylt     if (!delegate)
4517509a596Sjeremylt       // LCOV_EXCL_START
4527509a596Sjeremylt       return CeedError(ceed, 1, "Backend does not support "
4537509a596Sjeremylt                        "ElemRestrictionCreateBlocked");
4547509a596Sjeremylt     // LCOV_EXCL_STOP
4557509a596Sjeremylt 
4567509a596Sjeremylt     ierr = CeedElemRestrictionCreateBlockedStrided(delegate, nelem, elemsize,
457d979a051Sjeremylt            blksize, ncomp, lsize, strides, rstr);
4587509a596Sjeremylt     CeedChk(ierr);
4597509a596Sjeremylt     return 0;
4607509a596Sjeremylt   }
4617509a596Sjeremylt 
4627509a596Sjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
4637509a596Sjeremylt 
4647509a596Sjeremylt   (*rstr)->ceed = ceed;
4657509a596Sjeremylt   ceed->refcount++;
4667509a596Sjeremylt   (*rstr)->refcount = 1;
4677509a596Sjeremylt   (*rstr)->nelem = nelem;
4687509a596Sjeremylt   (*rstr)->elemsize = elemsize;
4697509a596Sjeremylt   (*rstr)->ncomp = ncomp;
470d979a051Sjeremylt   (*rstr)->lsize = lsize;
4717509a596Sjeremylt   (*rstr)->nblk = nblk;
4727509a596Sjeremylt   (*rstr)->blksize = blksize;
4737509a596Sjeremylt   ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr);
4747509a596Sjeremylt   for (int i = 0; i<3; i++)
4757509a596Sjeremylt     (*rstr)->strides[i] = strides[i];
4767509a596Sjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
4777509a596Sjeremylt          NULL, *rstr); CeedChk(ierr);
4787509a596Sjeremylt 
4797509a596Sjeremylt   return 0;
4807509a596Sjeremylt }
4817509a596Sjeremylt 
4827509a596Sjeremylt /**
483b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
484b11c1e72Sjeremylt 
4854ce2993fSjeremylt   @param rstr  CeedElemRestriction
486b11c1e72Sjeremylt   @param lvec  The address of the L-vector to be created, or NULL
487b11c1e72Sjeremylt   @param evec  The address of the E-vector to be created, or NULL
488b11c1e72Sjeremylt 
489b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
490dfdf5a53Sjeremylt 
4917a982d89SJeremy L. Thompson   @ref User
492b11c1e72Sjeremylt **/
4934ce2993fSjeremylt int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *lvec,
494d7b241e6Sjeremylt                                     CeedVector *evec) {
495d7b241e6Sjeremylt   int ierr;
496d7b241e6Sjeremylt   CeedInt n, m;
497d979a051Sjeremylt   m = rstr->lsize;
4984ce2993fSjeremylt   n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
499d7b241e6Sjeremylt   if (lvec) {
5004ce2993fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, m, lvec); CeedChk(ierr);
501d7b241e6Sjeremylt   }
502d7b241e6Sjeremylt   if (evec) {
5034ce2993fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, n, evec); CeedChk(ierr);
504d7b241e6Sjeremylt   }
505d7b241e6Sjeremylt   return 0;
506d7b241e6Sjeremylt }
507d7b241e6Sjeremylt 
508d7b241e6Sjeremylt /**
509d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
510d7b241e6Sjeremylt 
5114ce2993fSjeremylt   @param rstr    CeedElemRestriction
512d7b241e6Sjeremylt   @param tmode   Apply restriction or transpose
513d979a051Sjeremylt   @param u       Input vector (of size @a lsize when tmode=CEED_NOTRANSPOSE)
514a8d32208Sjeremylt   @param ru      Output vector (of shape [@a nelem * @a elemsize] when
5157aaeacdcSjeremylt                    tmode=CEED_NOTRANSPOSE). Ordering of the e-vector is decided
5167aaeacdcSjeremylt                    by the backend.
517d7b241e6Sjeremylt   @param request Request or CEED_REQUEST_IMMEDIATE
518b11c1e72Sjeremylt 
519b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
520dfdf5a53Sjeremylt 
5217a982d89SJeremy L. Thompson   @ref User
522b11c1e72Sjeremylt **/
5234ce2993fSjeremylt int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode tmode,
524a8d32208Sjeremylt                              CeedVector u, CeedVector ru,
525a8d32208Sjeremylt                              CeedRequest *request) {
526d7b241e6Sjeremylt   CeedInt m,n;
527d7b241e6Sjeremylt   int ierr;
528d7b241e6Sjeremylt 
529d7b241e6Sjeremylt   if (tmode == CEED_NOTRANSPOSE) {
5304ce2993fSjeremylt     m = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
531d979a051Sjeremylt     n = rstr->lsize;
532d7b241e6Sjeremylt   } else {
533d979a051Sjeremylt     m = rstr->lsize;
5344ce2993fSjeremylt     n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
535d7b241e6Sjeremylt   }
536d7b241e6Sjeremylt   if (n != u->length)
537c042f62fSJeremy L Thompson     // LCOV_EXCL_START
5381d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Input vector size %d not compatible with "
5391d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
540c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
541a8d32208Sjeremylt   if (m != ru->length)
542c042f62fSJeremy L Thompson     // LCOV_EXCL_START
5431d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Output vector size %d not compatible with "
544a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
545c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
546074cb416Sjeremylt   ierr = rstr->Apply(rstr, tmode, u, ru, request); CeedChk(ierr);
547d7b241e6Sjeremylt 
548d7b241e6Sjeremylt   return 0;
549d7b241e6Sjeremylt }
550d7b241e6Sjeremylt 
551d7b241e6Sjeremylt /**
552d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
553be9261b7Sjeremylt 
554be9261b7Sjeremylt   @param rstr    CeedElemRestriction
5551f37b403Sjeremylt   @param block   Block number to restrict to/from, i.e. block=0 will handle
5561f37b403Sjeremylt                    elements [0 : blksize] and block=3 will handle elements
5571f37b403Sjeremylt                    [3*blksize : 4*blksize]
558be9261b7Sjeremylt   @param tmode   Apply restriction or transpose
559d979a051Sjeremylt   @param u       Input vector (of size @a lsize when tmode=CEED_NOTRANSPOSE)
560a8d32208Sjeremylt   @param ru      Output vector (of shape [@a blksize * @a elemsize] when
5617aaeacdcSjeremylt                    tmode=CEED_NOTRANSPOSE). Ordering of the e-vector is decided
5627aaeacdcSjeremylt                    by the backend.
563be9261b7Sjeremylt   @param request Request or CEED_REQUEST_IMMEDIATE
564be9261b7Sjeremylt 
565be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
566be9261b7Sjeremylt 
5677a982d89SJeremy L. Thompson   @ref Backend
568be9261b7Sjeremylt **/
569be9261b7Sjeremylt int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block,
570a8d32208Sjeremylt                                   CeedTransposeMode tmode, CeedVector u,
571a8d32208Sjeremylt                                   CeedVector ru, CeedRequest *request) {
572be9261b7Sjeremylt   CeedInt m,n;
573be9261b7Sjeremylt   int ierr;
574be9261b7Sjeremylt 
575be9261b7Sjeremylt   if (tmode == CEED_NOTRANSPOSE) {
576be9261b7Sjeremylt     m = rstr->blksize * rstr->elemsize * rstr->ncomp;
577d979a051Sjeremylt     n = rstr->lsize;
578be9261b7Sjeremylt   } else {
579d979a051Sjeremylt     m = rstr->lsize;
580be9261b7Sjeremylt     n = rstr->blksize * rstr->elemsize * rstr->ncomp;
581be9261b7Sjeremylt   }
582be9261b7Sjeremylt   if (n != u->length)
583c042f62fSJeremy L Thompson     // LCOV_EXCL_START
5841d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Input vector size %d not compatible with "
5851d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
586c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
587a8d32208Sjeremylt   if (m != ru->length)
588c042f62fSJeremy L Thompson     // LCOV_EXCL_START
5891d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Output vector size %d not compatible with "
590a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
591c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
592be9261b7Sjeremylt   if (rstr->blksize*block > rstr->nelem)
593c042f62fSJeremy L Thompson     // LCOV_EXCL_START
5941d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Cannot retrieve block %d, element %d > "
5951d102b48SJeremy L Thompson                      "total elements %d", block, rstr->blksize*block,
5961d102b48SJeremy L Thompson                      rstr->nelem);
597c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
598074cb416Sjeremylt   ierr = rstr->ApplyBlock(rstr, block, tmode, u, ru, request);
599be9261b7Sjeremylt   CeedChk(ierr);
600be9261b7Sjeremylt 
601be9261b7Sjeremylt   return 0;
602be9261b7Sjeremylt }
603be9261b7Sjeremylt 
604be9261b7Sjeremylt /**
605d979a051Sjeremylt   @brief Get the L-vector component stride
606a681ae63Sjeremylt 
607a681ae63Sjeremylt   @param rstr             CeedElemRestriction
608d979a051Sjeremylt   @param[out] compstride  Variable to store component stride
609a681ae63Sjeremylt 
610a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
611a681ae63Sjeremylt 
612a681ae63Sjeremylt   @ref Backend
613a681ae63Sjeremylt **/
614d979a051Sjeremylt int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr,
615d979a051Sjeremylt                                      CeedInt *compstride) {
616d979a051Sjeremylt   *compstride = rstr->compstride;
617a681ae63Sjeremylt   return 0;
618a681ae63Sjeremylt }
619a681ae63Sjeremylt 
620a681ae63Sjeremylt /**
621a681ae63Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
622a681ae63Sjeremylt 
623a681ae63Sjeremylt   @param rstr             CeedElemRestriction
624a681ae63Sjeremylt   @param[out] numelem     Variable to store number of elements
625a681ae63Sjeremylt 
626a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
627a681ae63Sjeremylt 
628a681ae63Sjeremylt   @ref Backend
629a681ae63Sjeremylt **/
630a681ae63Sjeremylt int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
631a681ae63Sjeremylt                                       CeedInt *numelem) {
632a681ae63Sjeremylt   *numelem = rstr->nelem;
633a681ae63Sjeremylt   return 0;
634a681ae63Sjeremylt }
635a681ae63Sjeremylt 
636a681ae63Sjeremylt /**
637a681ae63Sjeremylt   @brief Get the size of elements in the CeedElemRestriction
638a681ae63Sjeremylt 
639a681ae63Sjeremylt   @param rstr             CeedElemRestriction
640a681ae63Sjeremylt   @param[out] elemsize    Variable to store size of elements
641a681ae63Sjeremylt 
642a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
643a681ae63Sjeremylt 
644a681ae63Sjeremylt   @ref Backend
645a681ae63Sjeremylt **/
646a681ae63Sjeremylt int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
647a681ae63Sjeremylt                                       CeedInt *elemsize) {
648a681ae63Sjeremylt   *elemsize = rstr->elemsize;
649a681ae63Sjeremylt   return 0;
650a681ae63Sjeremylt }
651a681ae63Sjeremylt 
652a681ae63Sjeremylt /**
653d979a051Sjeremylt   @brief Get the size of the l-vector for a CeedElemRestriction
654a681ae63Sjeremylt 
655a681ae63Sjeremylt   @param rstr             CeedElemRestriction
656a681ae63Sjeremylt   @param[out] numnodes    Variable to store number of nodes
657a681ae63Sjeremylt 
658a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
659a681ae63Sjeremylt 
660a681ae63Sjeremylt   @ref Backend
661a681ae63Sjeremylt **/
662d979a051Sjeremylt int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr,
663d979a051Sjeremylt                                       CeedInt *lsize) {
664d979a051Sjeremylt   *lsize = rstr->lsize;
665a681ae63Sjeremylt   return 0;
666a681ae63Sjeremylt }
667a681ae63Sjeremylt 
668a681ae63Sjeremylt /**
669a681ae63Sjeremylt   @brief Get the number of components in the elements of a
670a681ae63Sjeremylt          CeedElemRestriction
671a681ae63Sjeremylt 
672a681ae63Sjeremylt   @param rstr             CeedElemRestriction
673a681ae63Sjeremylt   @param[out] numcomp     Variable to store number of components
674a681ae63Sjeremylt 
675a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
676a681ae63Sjeremylt 
677a681ae63Sjeremylt   @ref Backend
678a681ae63Sjeremylt **/
679a681ae63Sjeremylt int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
680a681ae63Sjeremylt                                         CeedInt *numcomp) {
681a681ae63Sjeremylt   *numcomp = rstr->ncomp;
682a681ae63Sjeremylt   return 0;
683a681ae63Sjeremylt }
684a681ae63Sjeremylt 
685a681ae63Sjeremylt /**
686a681ae63Sjeremylt   @brief Get the number of blocks in a CeedElemRestriction
687a681ae63Sjeremylt 
688a681ae63Sjeremylt   @param rstr             CeedElemRestriction
689a681ae63Sjeremylt   @param[out] numblock    Variable to store number of blocks
690a681ae63Sjeremylt 
691a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
692a681ae63Sjeremylt 
693a681ae63Sjeremylt   @ref Backend
694a681ae63Sjeremylt **/
695a681ae63Sjeremylt int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
696a681ae63Sjeremylt                                     CeedInt *numblock) {
697a681ae63Sjeremylt   *numblock = rstr->nblk;
698a681ae63Sjeremylt   return 0;
699a681ae63Sjeremylt }
700a681ae63Sjeremylt 
701a681ae63Sjeremylt /**
702a681ae63Sjeremylt   @brief Get the size of blocks in the CeedElemRestriction
703a681ae63Sjeremylt 
704a681ae63Sjeremylt   @param rstr             CeedElemRestriction
705a681ae63Sjeremylt   @param[out] blksize     Variable to store size of blocks
706a681ae63Sjeremylt 
707a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
708a681ae63Sjeremylt 
709a681ae63Sjeremylt   @ref Backend
710a681ae63Sjeremylt **/
711a681ae63Sjeremylt int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
712a681ae63Sjeremylt                                     CeedInt *blksize) {
713a681ae63Sjeremylt   *blksize = rstr->blksize;
714a681ae63Sjeremylt   return 0;
715a681ae63Sjeremylt }
716a681ae63Sjeremylt 
717a681ae63Sjeremylt /**
718d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
7191469ee4dSjeremylt 
7201469ee4dSjeremylt   @param rstr             CeedElemRestriction
721d979a051Sjeremylt   @param[out] mult        Vector to store multiplicity (of size lsize)
7221469ee4dSjeremylt 
7231469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
7241469ee4dSjeremylt 
7257a982d89SJeremy L. Thompson   @ref User
7261469ee4dSjeremylt **/
7271469ee4dSjeremylt int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr,
7281469ee4dSjeremylt                                        CeedVector mult) {
7291469ee4dSjeremylt   int ierr;
7301469ee4dSjeremylt   CeedVector evec;
7311469ee4dSjeremylt 
7321469ee4dSjeremylt   // Create and set evec
7331469ee4dSjeremylt   ierr = CeedElemRestrictionCreateVector(rstr, NULL, &evec); CeedChk(ierr);
7341469ee4dSjeremylt   ierr = CeedVectorSetValue(evec, 1.0); CeedChk(ierr);
735fa9eac48SJed Brown   ierr = CeedVectorSetValue(mult, 0.0); CeedChk(ierr);
7361469ee4dSjeremylt 
7371469ee4dSjeremylt   // Apply to get multiplicity
738a8d32208Sjeremylt   ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, evec, mult,
739efc78312Sjeremylt                                   CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
7401469ee4dSjeremylt 
7411469ee4dSjeremylt   // Cleanup
7421469ee4dSjeremylt   ierr = CeedVectorDestroy(&evec); CeedChk(ierr);
7431469ee4dSjeremylt 
7441469ee4dSjeremylt   return 0;
7451469ee4dSjeremylt }
7461469ee4dSjeremylt 
7471469ee4dSjeremylt /**
748f02ca4a2SJed Brown   @brief View a CeedElemRestriction
749f02ca4a2SJed Brown 
750f02ca4a2SJed Brown   @param[in] rstr    CeedElemRestriction to view
751f02ca4a2SJed Brown   @param[in] stream  Stream to write; typically stdout/stderr or a file
752f02ca4a2SJed Brown 
753f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
754f02ca4a2SJed Brown 
7557a982d89SJeremy L. Thompson   @ref User
756f02ca4a2SJed Brown **/
757f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
7587509a596Sjeremylt   char stridesstr[500];
7597509a596Sjeremylt   if (rstr->strides)
7607509a596Sjeremylt     sprintf(stridesstr, "[%d, %d, %d]", rstr->strides[0], rstr->strides[1],
7617509a596Sjeremylt             rstr->strides[2]);
762d979a051Sjeremylt   else
763d979a051Sjeremylt     sprintf(stridesstr, "%d", rstr->compstride);
7647509a596Sjeremylt 
7650036de2cSjeremylt   fprintf(stream, "%sCeedElemRestriction from (%d, %d) to %d elements with %d "
7660036de2cSjeremylt           "nodes each and %s %s\n", rstr->blksize > 1 ? "Blocked " : "",
767d979a051Sjeremylt           rstr->lsize, rstr->ncomp, rstr->nelem, rstr->elemsize,
768d979a051Sjeremylt           rstr->strides ? "strides" : "component stride", stridesstr);
769f02ca4a2SJed Brown   return 0;
770f02ca4a2SJed Brown }
771f02ca4a2SJed Brown 
772f02ca4a2SJed Brown /**
773b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
774b11c1e72Sjeremylt 
7754ce2993fSjeremylt   @param rstr  CeedElemRestriction to destroy
776b11c1e72Sjeremylt 
777b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
778dfdf5a53Sjeremylt 
7797a982d89SJeremy L. Thompson   @ref User
780b11c1e72Sjeremylt **/
7814ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
782d7b241e6Sjeremylt   int ierr;
783d7b241e6Sjeremylt 
7841d102b48SJeremy L Thompson   if (!*rstr || --(*rstr)->refcount > 0)
7851d102b48SJeremy L Thompson     return 0;
7864ce2993fSjeremylt   if ((*rstr)->Destroy) {
7874ce2993fSjeremylt     ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr);
788d7b241e6Sjeremylt   }
7897509a596Sjeremylt   ierr = CeedFree(&(*rstr)->strides); CeedChk(ierr);
7904ce2993fSjeremylt   ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr);
7914ce2993fSjeremylt   ierr = CeedFree(rstr); CeedChk(ierr);
792d7b241e6Sjeremylt   return 0;
793d7b241e6Sjeremylt }
794d7b241e6Sjeremylt 
795d7b241e6Sjeremylt /// @}
796