xref: /libCEED/interface/ceed-elemrestriction.c (revision 7a982d89c751e293e39d23a7c44a161cef1fcd06)
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 
20*7a982d89SJeremy L. Thompson /// @file
21*7a982d89SJeremy L. Thompson /// Implementation of CeedElemRestriction interfaces
22*7a982d89SJeremy L. Thompson 
23*7a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
24*7a982d89SJeremy L. Thompson /// CeedElemRestriction Library Internal Functions
25*7a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
26*7a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionDeveloper
27*7a982d89SJeremy L. Thompson /// @{
28*7a982d89SJeremy L. Thompson 
29*7a982d89SJeremy L. Thompson /**
30*7a982d89SJeremy L. Thompson   @brief Permute and pad indices for a blocked restriction
31*7a982d89SJeremy L. Thompson 
32*7a982d89SJeremy L. Thompson   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
33*7a982d89SJeremy L. Thompson                       ordered list of the indices (into the input CeedVector)
34*7a982d89SJeremy L. Thompson                       for the unknowns corresponding to element i, where
35*7a982d89SJeremy L. Thompson                       0 <= i < @a nelem. All indices must be in the range
36*7a982d89SJeremy L. Thompson                       [0, @a nnodes).
37*7a982d89SJeremy L. Thompson   @param blkindices Array of permuted and padded indices of
38*7a982d89SJeremy L. Thompson                       shape [@a nblk, @a elemsize, @a blksize].
39*7a982d89SJeremy L. Thompson   @param nblk       Number of blocks
40*7a982d89SJeremy L. Thompson   @param nelem      Number of elements
41*7a982d89SJeremy L. Thompson   @param blksize    Number of elements in a block
42*7a982d89SJeremy L. Thompson   @param elemsize   Size of each element
43*7a982d89SJeremy L. Thompson 
44*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
45*7a982d89SJeremy L. Thompson 
46*7a982d89SJeremy L. Thompson   @ref Utility
47*7a982d89SJeremy L. Thompson **/
48*7a982d89SJeremy L. Thompson int CeedPermutePadIndices(const CeedInt *indices, CeedInt *blkindices,
49*7a982d89SJeremy L. Thompson                           CeedInt nblk, CeedInt nelem, CeedInt blksize,
50*7a982d89SJeremy L. Thompson                           CeedInt elemsize) {
51*7a982d89SJeremy L. Thompson   for (CeedInt e = 0; e < nblk*blksize; e+=blksize)
52*7a982d89SJeremy L. Thompson     for (int j = 0; j < blksize; j++)
53*7a982d89SJeremy L. Thompson       for (int k = 0; k < elemsize; k++)
54*7a982d89SJeremy L. Thompson         blkindices[e*elemsize + k*blksize + j]
55*7a982d89SJeremy L. Thompson           = indices[CeedIntMin(e+j,nelem-1)*elemsize + k];
56*7a982d89SJeremy L. Thompson   return 0;
57*7a982d89SJeremy L. Thompson }
58*7a982d89SJeremy L. Thompson 
59*7a982d89SJeremy L. Thompson /// @}
60*7a982d89SJeremy L. Thompson 
61*7a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
62*7a982d89SJeremy L. Thompson /// CeedElemRestriction Backend API
63*7a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
64*7a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionBackend
65*7a982d89SJeremy L. Thompson /// @{
66*7a982d89SJeremy L. Thompson 
67*7a982d89SJeremy L. Thompson /**
68*7a982d89SJeremy L. Thompson   @brief Get the Ceed associated with a CeedElemRestriction
69*7a982d89SJeremy L. Thompson 
70*7a982d89SJeremy L. Thompson   @param rstr             CeedElemRestriction
71*7a982d89SJeremy L. Thompson   @param[out] ceed        Variable to store Ceed
72*7a982d89SJeremy L. Thompson 
73*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
74*7a982d89SJeremy L. Thompson 
75*7a982d89SJeremy L. Thompson   @ref Backend
76*7a982d89SJeremy L. Thompson **/
77*7a982d89SJeremy L. Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
78*7a982d89SJeremy L. Thompson   *ceed = rstr->ceed;
79*7a982d89SJeremy L. Thompson   return 0;
80*7a982d89SJeremy L. Thompson }
81*7a982d89SJeremy L. Thompson 
82*7a982d89SJeremy L. Thompson /**
83*7a982d89SJeremy L. Thompson   @brief Get the L-vector interlaced mode of a CeedElemRestriction
84*7a982d89SJeremy L. Thompson 
85*7a982d89SJeremy L. Thompson   @param rstr             CeedElemRestriction
86*7a982d89SJeremy L. Thompson   @param[out] imode       Variable to store imode
87*7a982d89SJeremy L. Thompson 
88*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
89*7a982d89SJeremy L. Thompson 
90*7a982d89SJeremy L. Thompson   @ref Backend
91*7a982d89SJeremy L. Thompson **/
92*7a982d89SJeremy L. Thompson int CeedElemRestrictionGetIMode(CeedElemRestriction rstr,
93*7a982d89SJeremy L. Thompson                                 CeedInterlaceMode *imode) {
94*7a982d89SJeremy L. Thompson   *imode = rstr->imode;
95*7a982d89SJeremy L. Thompson   return 0;
96*7a982d89SJeremy L. Thompson }
97*7a982d89SJeremy L. Thompson 
98*7a982d89SJeremy L. Thompson /**
99*7a982d89SJeremy L. Thompson   @brief Get the total number of elements in the range of a CeedElemRestriction
100*7a982d89SJeremy L. Thompson 
101*7a982d89SJeremy L. Thompson   @param rstr             CeedElemRestriction
102*7a982d89SJeremy L. Thompson   @param[out] numelem     Variable to store number of elements
103*7a982d89SJeremy L. Thompson 
104*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
105*7a982d89SJeremy L. Thompson 
106*7a982d89SJeremy L. Thompson   @ref Backend
107*7a982d89SJeremy L. Thompson **/
108*7a982d89SJeremy L. Thompson int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
109*7a982d89SJeremy L. Thompson                                       CeedInt *numelem) {
110*7a982d89SJeremy L. Thompson   *numelem = rstr->nelem;
111*7a982d89SJeremy L. Thompson   return 0;
112*7a982d89SJeremy L. Thompson }
113*7a982d89SJeremy L. Thompson 
114*7a982d89SJeremy L. Thompson /**
115*7a982d89SJeremy L. Thompson   @brief Get the size of elements in the CeedElemRestriction
116*7a982d89SJeremy L. Thompson 
117*7a982d89SJeremy L. Thompson   @param rstr             CeedElemRestriction
118*7a982d89SJeremy L. Thompson   @param[out] elemsize    Variable to store size of elements
119*7a982d89SJeremy L. Thompson 
120*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
121*7a982d89SJeremy L. Thompson 
122*7a982d89SJeremy L. Thompson   @ref Backend
123*7a982d89SJeremy L. Thompson **/
124*7a982d89SJeremy L. Thompson int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
125*7a982d89SJeremy L. Thompson                                       CeedInt *elemsize) {
126*7a982d89SJeremy L. Thompson   *elemsize = rstr->elemsize;
127*7a982d89SJeremy L. Thompson   return 0;
128*7a982d89SJeremy L. Thompson }
129*7a982d89SJeremy L. Thompson 
130*7a982d89SJeremy L. Thompson /**
131*7a982d89SJeremy L. Thompson   @brief Get the number of degrees of freedom in the range of a
132*7a982d89SJeremy L. Thompson          CeedElemRestriction
133*7a982d89SJeremy L. Thompson 
134*7a982d89SJeremy L. Thompson   @param rstr             CeedElemRestriction
135*7a982d89SJeremy L. Thompson   @param[out] numnodes    Variable to store number of nodes
136*7a982d89SJeremy L. Thompson 
137*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
138*7a982d89SJeremy L. Thompson 
139*7a982d89SJeremy L. Thompson   @ref Backend
140*7a982d89SJeremy L. Thompson **/
141*7a982d89SJeremy L. Thompson int CeedElemRestrictionGetNumNodes(CeedElemRestriction rstr,
142*7a982d89SJeremy L. Thompson                                    CeedInt *numnodes) {
143*7a982d89SJeremy L. Thompson   *numnodes = rstr->nnodes;
144*7a982d89SJeremy L. Thompson   return 0;
145*7a982d89SJeremy L. Thompson }
146*7a982d89SJeremy L. Thompson 
147*7a982d89SJeremy L. Thompson /**
148*7a982d89SJeremy L. Thompson   @brief Get the number of components in the elements of a
149*7a982d89SJeremy L. Thompson          CeedElemRestriction
150*7a982d89SJeremy L. Thompson 
151*7a982d89SJeremy L. Thompson   @param rstr             CeedElemRestriction
152*7a982d89SJeremy L. Thompson   @param[out] numcomp     Variable to store number of components
153*7a982d89SJeremy L. Thompson 
154*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
155*7a982d89SJeremy L. Thompson 
156*7a982d89SJeremy L. Thompson   @ref Backend
157*7a982d89SJeremy L. Thompson **/
158*7a982d89SJeremy L. Thompson int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
159*7a982d89SJeremy L. Thompson                                         CeedInt *numcomp) {
160*7a982d89SJeremy L. Thompson   *numcomp = rstr->ncomp;
161*7a982d89SJeremy L. Thompson   return 0;
162*7a982d89SJeremy L. Thompson }
163*7a982d89SJeremy L. Thompson 
164*7a982d89SJeremy L. Thompson /**
165*7a982d89SJeremy L. Thompson   @brief Get the number of blocks in a CeedElemRestriction
166*7a982d89SJeremy L. Thompson 
167*7a982d89SJeremy L. Thompson   @param rstr             CeedElemRestriction
168*7a982d89SJeremy L. Thompson   @param[out] numblock    Variable to store number of blocks
169*7a982d89SJeremy L. Thompson 
170*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
171*7a982d89SJeremy L. Thompson 
172*7a982d89SJeremy L. Thompson   @ref Backend
173*7a982d89SJeremy L. Thompson **/
174*7a982d89SJeremy L. Thompson int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
175*7a982d89SJeremy L. Thompson                                     CeedInt *numblock) {
176*7a982d89SJeremy L. Thompson   *numblock = rstr->nblk;
177*7a982d89SJeremy L. Thompson   return 0;
178*7a982d89SJeremy L. Thompson }
179*7a982d89SJeremy L. Thompson 
180*7a982d89SJeremy L. Thompson /**
181*7a982d89SJeremy L. Thompson   @brief Get the size of blocks in the CeedElemRestriction
182*7a982d89SJeremy L. Thompson 
183*7a982d89SJeremy L. Thompson   @param rstr             CeedElemRestriction
184*7a982d89SJeremy L. Thompson   @param[out] blksize     Variable to store size of blocks
185*7a982d89SJeremy L. Thompson 
186*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
187*7a982d89SJeremy L. Thompson 
188*7a982d89SJeremy L. Thompson   @ref Backend
189*7a982d89SJeremy L. Thompson **/
190*7a982d89SJeremy L. Thompson int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
191*7a982d89SJeremy L. Thompson                                     CeedInt *blksize) {
192*7a982d89SJeremy L. Thompson   *blksize = rstr->blksize;
193*7a982d89SJeremy L. Thompson   return 0;
194*7a982d89SJeremy L. Thompson }
195*7a982d89SJeremy L. Thompson 
196*7a982d89SJeremy L. Thompson /**
197*7a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedElemRestriction
198*7a982d89SJeremy L. Thompson 
199*7a982d89SJeremy L. Thompson   @param rstr             CeedElemRestriction
200*7a982d89SJeremy L. Thompson   @param[out] data        Variable to store data
201*7a982d89SJeremy L. Thompson 
202*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
203*7a982d89SJeremy L. Thompson 
204*7a982d89SJeremy L. Thompson   @ref Backend
205*7a982d89SJeremy L. Thompson **/
206*7a982d89SJeremy L. Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void **data) {
207*7a982d89SJeremy L. Thompson   *data = rstr->data;
208*7a982d89SJeremy L. Thompson   return 0;
209*7a982d89SJeremy L. Thompson }
210*7a982d89SJeremy L. Thompson 
211*7a982d89SJeremy L. Thompson /**
212*7a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedElemRestriction
213*7a982d89SJeremy L. Thompson 
214*7a982d89SJeremy L. Thompson   @param[out] rstr        CeedElemRestriction
215*7a982d89SJeremy L. Thompson   @param data             Data to set
216*7a982d89SJeremy L. Thompson 
217*7a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
218*7a982d89SJeremy L. Thompson 
219*7a982d89SJeremy L. Thompson   @ref Backend
220*7a982d89SJeremy L. Thompson **/
221*7a982d89SJeremy L. Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void **data) {
222*7a982d89SJeremy L. Thompson   rstr->data = *data;
223*7a982d89SJeremy L. Thompson   return 0;
224*7a982d89SJeremy L. Thompson }
225*7a982d89SJeremy L. Thompson 
226*7a982d89SJeremy L. Thompson /// @}
227*7a982d89SJeremy L. Thompson 
22815910d16Sjeremylt /// @cond DOXYGEN_SKIP
22915910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
23015910d16Sjeremylt /// @endcond
23115910d16Sjeremylt 
232*7a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
233*7a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
234*7a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
235*7a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
236d7b241e6Sjeremylt /// @{
237d7b241e6Sjeremylt 
238*7a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
239*7a982d89SJeremy L. Thompson const CeedInt CEED_STRIDES_BACKEND[3] = {};
240*7a982d89SJeremy L. Thompson 
241*7a982d89SJeremy L. Thompson /// Indicate that no ElemRestriction is provided by the user
242*7a982d89SJeremy L. Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE =
243*7a982d89SJeremy L. Thompson   &ceed_elemrestriction_none;
244*7a982d89SJeremy L. Thompson 
245d7b241e6Sjeremylt /**
246b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
247d7b241e6Sjeremylt 
248b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
24961dbc9d2Sjeremylt   @param imode      Ordering of the ncomp components, i.e. it specifies
250a8d32208Sjeremylt                       the ordering of the components of the L-vector used
25161dbc9d2Sjeremylt                       by this CeedElemRestriction. CEED_NONINTERLACED indicates
25261dbc9d2Sjeremylt                       the component is the outermost index and CEED_INTERLACED
253a8d32208Sjeremylt                       indicates the component is the innermost index in
254a8d32208Sjeremylt                       ordering of the L-vector.
255b11c1e72Sjeremylt   @param nelem      Number of elements described in the @a indices array
256b11c1e72Sjeremylt   @param elemsize   Size (number of "nodes") per element
2578795c945Sjeremylt   @param nnodes     The number of nodes in the L-vector. The input CeedVector
2588795c945Sjeremylt                       to which the restriction will be applied is of size
2598795c945Sjeremylt                       @a nnodes * @a ncomp. This size may include data
260d7b241e6Sjeremylt                       used by other CeedElemRestriction objects describing
261d7b241e6Sjeremylt                       different types of elements.
262b11c1e72Sjeremylt   @param ncomp      Number of field components per interpolation node
26395bb1877Svaleriabarra                       (1 for scalar fields)
264b11c1e72Sjeremylt   @param mtype      Memory type of the @a indices array, see CeedMemType
265b11c1e72Sjeremylt   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
2668795c945Sjeremylt   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
2678795c945Sjeremylt                       ordered list of the indices (into the input CeedVector)
2688795c945Sjeremylt                       for the unknowns corresponding to element i, where
26934138859Sjeremylt                       0 <= i < @a nelem. All indices must be in the range
27023e8ed12Sjeremylt                       [0, @a nnodes - 1].
2714ce2993fSjeremylt   @param[out] rstr  Address of the variable where the newly created
272b11c1e72Sjeremylt                       CeedElemRestriction will be stored
273d7b241e6Sjeremylt 
274b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
275dfdf5a53Sjeremylt 
276*7a982d89SJeremy L. Thompson   @ref User
277b11c1e72Sjeremylt **/
27861dbc9d2Sjeremylt int CeedElemRestrictionCreate(Ceed ceed, CeedInterlaceMode imode,
2797509a596Sjeremylt                               CeedInt nelem, CeedInt elemsize, CeedInt nnodes,
2807509a596Sjeremylt                               CeedInt ncomp, CeedMemType mtype,
2817509a596Sjeremylt                               CeedCopyMode cmode, const CeedInt *indices,
2824ce2993fSjeremylt                               CeedElemRestriction *rstr) {
283d7b241e6Sjeremylt   int ierr;
284d7b241e6Sjeremylt 
2855fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
2865fe0d4faSjeremylt     Ceed delegate;
287aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
288aefd8378Sjeremylt     CeedChk(ierr);
2895fe0d4faSjeremylt 
2905fe0d4faSjeremylt     if (!delegate)
291c042f62fSJeremy L Thompson       // LCOV_EXCL_START
292d7b241e6Sjeremylt       return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
293c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
2945fe0d4faSjeremylt 
29561dbc9d2Sjeremylt     ierr = CeedElemRestrictionCreate(delegate, imode, nelem, elemsize,
2968795c945Sjeremylt                                      nnodes, ncomp, mtype, cmode,
2974ce2993fSjeremylt                                      indices, rstr); CeedChk(ierr);
2985fe0d4faSjeremylt     return 0;
2995fe0d4faSjeremylt   }
3005fe0d4faSjeremylt 
3014ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
3024ce2993fSjeremylt   (*rstr)->ceed = ceed;
303d7b241e6Sjeremylt   ceed->refcount++;
3044ce2993fSjeremylt   (*rstr)->refcount = 1;
30561dbc9d2Sjeremylt   (*rstr)->imode = imode;
3064ce2993fSjeremylt   (*rstr)->nelem = nelem;
3074ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
3088795c945Sjeremylt   (*rstr)->nnodes = nnodes;
3094ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
3104ce2993fSjeremylt   (*rstr)->nblk = nelem;
3114ce2993fSjeremylt   (*rstr)->blksize = 1;
3124ce2993fSjeremylt   ierr = ceed->ElemRestrictionCreate(mtype, cmode, indices, *rstr); CeedChk(ierr);
313d7b241e6Sjeremylt   return 0;
314d7b241e6Sjeremylt }
315d7b241e6Sjeremylt 
316d7b241e6Sjeremylt /**
3177509a596Sjeremylt   @brief Create a strided CeedElemRestriction
318d7b241e6Sjeremylt 
319b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
3207509a596Sjeremylt   @param nelem      Number of elements described by the restriction
321b11c1e72Sjeremylt   @param elemsize   Size (number of "nodes") per element
3228795c945Sjeremylt   @param nnodes     The number of nodes in the L-vector. The input CeedVector
3238795c945Sjeremylt                       to which the restriction will be applied is of size
3248795c945Sjeremylt                       @a nnodes * @a ncomp. This size may include data
325d7b241e6Sjeremylt                       used by other CeedElemRestriction objects describing
3268795c945Sjeremylt                       different types of elements.
327b11c1e72Sjeremylt   @param ncomp      Number of field components per interpolation node
32895bb1877Svaleriabarra                       (1 for scalar fields)
3297509a596Sjeremylt   @param strides    Array for strides between [nodes, components, elements].
3307509a596Sjeremylt                       The data for node i, component j, element k in the
3317509a596Sjeremylt                       L-vector is given by
3327509a596Sjeremylt                         i*strides[0] + j*strides[1] + k*strides[2]
3334ce2993fSjeremylt   @param rstr       Address of the variable where the newly created
334b11c1e72Sjeremylt                       CeedElemRestriction will be stored
335d7b241e6Sjeremylt 
336b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
337dfdf5a53Sjeremylt 
338*7a982d89SJeremy L. Thompson   @ref User
339b11c1e72Sjeremylt **/
3407509a596Sjeremylt int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt nelem, CeedInt elemsize,
341a8d32208Sjeremylt                                      CeedInt nnodes, CeedInt ncomp,
3428621c6c6SJeremy L Thompson                                      const CeedInt strides[3],
343f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
344d7b241e6Sjeremylt   int ierr;
345d7b241e6Sjeremylt 
3465fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
3475fe0d4faSjeremylt     Ceed delegate;
348aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
349aefd8378Sjeremylt     CeedChk(ierr);
3505fe0d4faSjeremylt 
3515fe0d4faSjeremylt     if (!delegate)
352c042f62fSJeremy L Thompson       // LCOV_EXCL_START
3531d102b48SJeremy L Thompson       return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
354c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
3555fe0d4faSjeremylt 
3567509a596Sjeremylt     ierr = CeedElemRestrictionCreateStrided(delegate, nelem, elemsize, nnodes,
3577509a596Sjeremylt                                             ncomp, strides, rstr); CeedChk(ierr);
3585fe0d4faSjeremylt     return 0;
3595fe0d4faSjeremylt   }
3605fe0d4faSjeremylt 
3614ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
3624ce2993fSjeremylt   (*rstr)->ceed = ceed;
363d7b241e6Sjeremylt   ceed->refcount++;
3644ce2993fSjeremylt   (*rstr)->refcount = 1;
3654ce2993fSjeremylt   (*rstr)->nelem = nelem;
3664ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
3678795c945Sjeremylt   (*rstr)->nnodes = nnodes;
3684ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
3694ce2993fSjeremylt   (*rstr)->nblk = nelem;
3704ce2993fSjeremylt   (*rstr)->blksize = 1;
3717509a596Sjeremylt   ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr);
3727509a596Sjeremylt   for (int i = 0; i<3; i++)
3737509a596Sjeremylt     (*rstr)->strides[i] = strides[i];
3741dfeef1dSjeremylt   ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL,
3751dfeef1dSjeremylt                                      *rstr);
3764b8bea3bSJed Brown   CeedChk(ierr);
377d7b241e6Sjeremylt   return 0;
378d7b241e6Sjeremylt }
379d7b241e6Sjeremylt 
380d7b241e6Sjeremylt /**
381b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
382d7b241e6Sjeremylt 
383d7b241e6Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created.
38461dbc9d2Sjeremylt   @param imode      Ordering of the ncomp components, i.e. it specifies
385a8d32208Sjeremylt                       the ordering of the components of the L-vector used
38661dbc9d2Sjeremylt                       by this CeedElemRestriction. CEED_NONINTERLACED indicates
38761dbc9d2Sjeremylt                       the component is the outermost index and CEED_INTERLACED
388a8d32208Sjeremylt                       indicates the component is the innermost index in
389a8d32208Sjeremylt                       ordering of the L-vector.
390d7b241e6Sjeremylt   @param nelem      Number of elements described in the @a indices array.
391b11c1e72Sjeremylt   @param elemsize   Size (number of unknowns) per element
392b11c1e72Sjeremylt   @param blksize    Number of elements in a block
3938795c945Sjeremylt   @param nnodes     The number of nodes in the L-vector. The input CeedVector
3948795c945Sjeremylt                       to which the restriction will be applied is of size
3958795c945Sjeremylt                       @a nnodes * @a ncomp. This size may include data
396d7b241e6Sjeremylt                       used by other CeedElemRestriction objects describing
397d7b241e6Sjeremylt                       different types of elements.
39895bb1877Svaleriabarra   @param ncomp      Number of field components per interpolation node
39995bb1877Svaleriabarra                       (1 for scalar fields)
400b11c1e72Sjeremylt   @param mtype      Memory type of the @a indices array, see CeedMemType
401b11c1e72Sjeremylt   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
4028795c945Sjeremylt   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
4038795c945Sjeremylt                       ordered list of the indices (into the input CeedVector)
4048795c945Sjeremylt                       for the unknowns corresponding to element i, where
40534138859Sjeremylt                       0 <= i < @a nelem. All indices must be in the range
4068795c945Sjeremylt                       [0, @a nnodes). The backend will permute and pad this
4078795c945Sjeremylt                       array to the desired ordering for the blocksize, which is
4088795c945Sjeremylt                       typically given by the backend. The default reordering is
4098795c945Sjeremylt                       to interlace elements.
4104ce2993fSjeremylt   @param rstr       Address of the variable where the newly created
411b11c1e72Sjeremylt                       CeedElemRestriction will be stored
412d7b241e6Sjeremylt 
413b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
414dfdf5a53Sjeremylt 
415*7a982d89SJeremy L. Thompson   @ref Backend
416b11c1e72Sjeremylt  **/
41761dbc9d2Sjeremylt int CeedElemRestrictionCreateBlocked(Ceed ceed,  CeedInterlaceMode imode,
418a8d32208Sjeremylt                                      CeedInt nelem, CeedInt elemsize,
4198795c945Sjeremylt                                      CeedInt blksize, CeedInt nnodes,
4208795c945Sjeremylt                                      CeedInt ncomp, CeedMemType mtype,
4218795c945Sjeremylt                                      CeedCopyMode cmode, const CeedInt *indices,
4224ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
423d7b241e6Sjeremylt   int ierr;
424d7b241e6Sjeremylt   CeedInt *blkindices;
425d7b241e6Sjeremylt   CeedInt nblk = (nelem / blksize) + !!(nelem % blksize);
426d7b241e6Sjeremylt 
4275fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
4285fe0d4faSjeremylt     Ceed delegate;
429aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
430aefd8378Sjeremylt     CeedChk(ierr);
4315fe0d4faSjeremylt 
4325fe0d4faSjeremylt     if (!delegate)
433c042f62fSJeremy L Thompson       // LCOV_EXCL_START
4341d102b48SJeremy L Thompson       return CeedError(ceed, 1, "Backend does not support "
4351d102b48SJeremy L Thompson                        "ElemRestrictionCreateBlocked");
436c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
4375fe0d4faSjeremylt 
43861dbc9d2Sjeremylt     ierr = CeedElemRestrictionCreateBlocked(delegate, imode, nelem, elemsize,
4398795c945Sjeremylt                                             blksize, nnodes, ncomp, mtype, cmode,
4404ce2993fSjeremylt                                             indices, rstr); CeedChk(ierr);
4415fe0d4faSjeremylt     return 0;
4425fe0d4faSjeremylt   }
443d7b241e6Sjeremylt 
4444ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
445d7b241e6Sjeremylt 
446de686571SJeremy L Thompson   ierr = CeedCalloc(nblk*blksize*elemsize, &blkindices); CeedChk(ierr);
4474b8bea3bSJed Brown   ierr = CeedPermutePadIndices(indices, blkindices, nblk, nelem, blksize,
4484b8bea3bSJed Brown                                elemsize);
449dfdf5a53Sjeremylt   CeedChk(ierr);
450d7b241e6Sjeremylt 
4514ce2993fSjeremylt   (*rstr)->ceed = ceed;
452d7b241e6Sjeremylt   ceed->refcount++;
4534ce2993fSjeremylt   (*rstr)->refcount = 1;
45461dbc9d2Sjeremylt   (*rstr)->imode = imode;
4554ce2993fSjeremylt   (*rstr)->nelem = nelem;
4564ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
4578795c945Sjeremylt   (*rstr)->nnodes = nnodes;
4584ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
4594ce2993fSjeremylt   (*rstr)->nblk = nblk;
4604ce2993fSjeremylt   (*rstr)->blksize = blksize;
461667bc5fcSjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
4627f823360Sjeremylt          (const CeedInt *) blkindices, *rstr); CeedChk(ierr);
463d7b241e6Sjeremylt 
4641d102b48SJeremy L Thompson   if (cmode == CEED_OWN_POINTER) {
465d7b241e6Sjeremylt     ierr = CeedFree(&indices); CeedChk(ierr);
4661d102b48SJeremy L Thompson   }
467d7b241e6Sjeremylt 
468d7b241e6Sjeremylt   return 0;
469d7b241e6Sjeremylt }
470d7b241e6Sjeremylt 
471b11c1e72Sjeremylt /**
4727509a596Sjeremylt   @brief Create a blocked strided CeedElemRestriction
4737509a596Sjeremylt 
4747509a596Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
4757509a596Sjeremylt   @param nelem      Number of elements described by the restriction
4767509a596Sjeremylt   @param elemsize   Size (number of "nodes") per element
4777509a596Sjeremylt   @param blksize    Number of elements in a block
4787509a596Sjeremylt   @param nnodes     The number of nodes in the L-vector. The input CeedVector
4797509a596Sjeremylt                       to which the restriction will be applied is of size
4807509a596Sjeremylt                       @a nnodes * @a ncomp. This size may include data
4817509a596Sjeremylt                       used by other CeedElemRestriction objects describing
4827509a596Sjeremylt                       different types of elements.
4837509a596Sjeremylt   @param ncomp      Number of field components per interpolation node
4847509a596Sjeremylt                       (1 for scalar fields)
4857509a596Sjeremylt   @param strides    Array for strides between [nodes, components, elements].
4867509a596Sjeremylt                       The data for node i, component j, element k in the
4877509a596Sjeremylt                       L-vector is given by
4887509a596Sjeremylt                         i*strides[0] + j*strides[1] + k*strides[2]
4897509a596Sjeremylt   @param rstr       Address of the variable where the newly created
4907509a596Sjeremylt                       CeedElemRestriction will be stored
4917509a596Sjeremylt 
4927509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
4937509a596Sjeremylt 
494*7a982d89SJeremy L. Thompson   @ref User
4957509a596Sjeremylt **/
4967509a596Sjeremylt int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt nelem,
4978621c6c6SJeremy L Thompson     CeedInt elemsize, CeedInt blksize, CeedInt nnodes, CeedInt ncomp,
4988621c6c6SJeremy L Thompson     const CeedInt strides[3], CeedElemRestriction *rstr) {
4997509a596Sjeremylt   int ierr;
5007509a596Sjeremylt   CeedInt nblk = (nelem / blksize) + !!(nelem % blksize);
5017509a596Sjeremylt 
5027509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
5037509a596Sjeremylt     Ceed delegate;
5047509a596Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
5057509a596Sjeremylt     CeedChk(ierr);
5067509a596Sjeremylt 
5077509a596Sjeremylt     if (!delegate)
5087509a596Sjeremylt       // LCOV_EXCL_START
5097509a596Sjeremylt       return CeedError(ceed, 1, "Backend does not support "
5107509a596Sjeremylt                        "ElemRestrictionCreateBlocked");
5117509a596Sjeremylt     // LCOV_EXCL_STOP
5127509a596Sjeremylt 
5137509a596Sjeremylt     ierr = CeedElemRestrictionCreateBlockedStrided(delegate, nelem, elemsize,
5148621c6c6SJeremy L Thompson            blksize, nnodes, ncomp, strides, rstr);
5157509a596Sjeremylt     CeedChk(ierr);
5167509a596Sjeremylt     return 0;
5177509a596Sjeremylt   }
5187509a596Sjeremylt 
5197509a596Sjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
5207509a596Sjeremylt 
5217509a596Sjeremylt   (*rstr)->ceed = ceed;
5227509a596Sjeremylt   ceed->refcount++;
5237509a596Sjeremylt   (*rstr)->refcount = 1;
5247509a596Sjeremylt   (*rstr)->nelem = nelem;
5257509a596Sjeremylt   (*rstr)->elemsize = elemsize;
5267509a596Sjeremylt   (*rstr)->nnodes = nnodes;
5277509a596Sjeremylt   (*rstr)->ncomp = ncomp;
5287509a596Sjeremylt   (*rstr)->nblk = nblk;
5297509a596Sjeremylt   (*rstr)->blksize = blksize;
5307509a596Sjeremylt   ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr);
5317509a596Sjeremylt   for (int i = 0; i<3; i++)
5327509a596Sjeremylt     (*rstr)->strides[i] = strides[i];
5337509a596Sjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
5347509a596Sjeremylt          NULL, *rstr); CeedChk(ierr);
5357509a596Sjeremylt 
5367509a596Sjeremylt   return 0;
5377509a596Sjeremylt }
5387509a596Sjeremylt 
5397509a596Sjeremylt /**
540b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
541b11c1e72Sjeremylt 
5424ce2993fSjeremylt   @param rstr  CeedElemRestriction
543b11c1e72Sjeremylt   @param lvec  The address of the L-vector to be created, or NULL
544b11c1e72Sjeremylt   @param evec  The address of the E-vector to be created, or NULL
545b11c1e72Sjeremylt 
546b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
547dfdf5a53Sjeremylt 
548*7a982d89SJeremy L. Thompson   @ref User
549b11c1e72Sjeremylt **/
5504ce2993fSjeremylt int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *lvec,
551d7b241e6Sjeremylt                                     CeedVector *evec) {
552d7b241e6Sjeremylt   int ierr;
553d7b241e6Sjeremylt   CeedInt n, m;
5548795c945Sjeremylt   m = rstr->nnodes * rstr->ncomp;
5554ce2993fSjeremylt   n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
556d7b241e6Sjeremylt   if (lvec) {
5574ce2993fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, m, lvec); CeedChk(ierr);
558d7b241e6Sjeremylt   }
559d7b241e6Sjeremylt   if (evec) {
5604ce2993fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, n, evec); CeedChk(ierr);
561d7b241e6Sjeremylt   }
562d7b241e6Sjeremylt   return 0;
563d7b241e6Sjeremylt }
564d7b241e6Sjeremylt 
565d7b241e6Sjeremylt /**
566d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
567d7b241e6Sjeremylt 
5684ce2993fSjeremylt   @param rstr    CeedElemRestriction
569d7b241e6Sjeremylt   @param tmode   Apply restriction or transpose
5707aaeacdcSjeremylt   @param u       Input vector (of shape [@a nnodes, @a ncomp] when
57161dbc9d2Sjeremylt                    tmode=CEED_NOTRANSPOSE, imode=CEED_INTERLACED)
572a8d32208Sjeremylt   @param ru      Output vector (of shape [@a nelem * @a elemsize] when
5737aaeacdcSjeremylt                    tmode=CEED_NOTRANSPOSE). Ordering of the e-vector is decided
5747aaeacdcSjeremylt                    by the backend.
575d7b241e6Sjeremylt   @param request Request or CEED_REQUEST_IMMEDIATE
576b11c1e72Sjeremylt 
577b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
578dfdf5a53Sjeremylt 
579*7a982d89SJeremy L. Thompson   @ref User
580b11c1e72Sjeremylt **/
5814ce2993fSjeremylt int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode tmode,
582a8d32208Sjeremylt                              CeedVector u, CeedVector ru,
583a8d32208Sjeremylt                              CeedRequest *request) {
584d7b241e6Sjeremylt   CeedInt m,n;
585d7b241e6Sjeremylt   int ierr;
586d7b241e6Sjeremylt 
587d7b241e6Sjeremylt   if (tmode == CEED_NOTRANSPOSE) {
5884ce2993fSjeremylt     m = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
5898795c945Sjeremylt     n = rstr->nnodes * rstr->ncomp;
590d7b241e6Sjeremylt   } else {
5918795c945Sjeremylt     m = rstr->nnodes * rstr->ncomp;
5924ce2993fSjeremylt     n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
593d7b241e6Sjeremylt   }
594d7b241e6Sjeremylt   if (n != u->length)
595c042f62fSJeremy L Thompson     // LCOV_EXCL_START
5961d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Input vector size %d not compatible with "
5971d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
598c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
599a8d32208Sjeremylt   if (m != ru->length)
600c042f62fSJeremy L Thompson     // LCOV_EXCL_START
6011d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Output vector size %d not compatible with "
602a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
603c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
604074cb416Sjeremylt   ierr = rstr->Apply(rstr, tmode, u, ru, request); CeedChk(ierr);
605d7b241e6Sjeremylt 
606d7b241e6Sjeremylt   return 0;
607d7b241e6Sjeremylt }
608d7b241e6Sjeremylt 
609d7b241e6Sjeremylt /**
610d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
611be9261b7Sjeremylt 
612be9261b7Sjeremylt   @param rstr    CeedElemRestriction
6131f37b403Sjeremylt   @param block   Block number to restrict to/from, i.e. block=0 will handle
6141f37b403Sjeremylt                    elements [0 : blksize] and block=3 will handle elements
6151f37b403Sjeremylt                    [3*blksize : 4*blksize]
616be9261b7Sjeremylt   @param tmode   Apply restriction or transpose
6177aaeacdcSjeremylt   @param u       Input vector (of shape [@a nnodes, @a ncomp] when
61861dbc9d2Sjeremylt                    tmode=CEED_NOTRANSPOSE, imode=CEED_INTERLACED)
619a8d32208Sjeremylt   @param ru      Output vector (of shape [@a blksize * @a elemsize] when
6207aaeacdcSjeremylt                    tmode=CEED_NOTRANSPOSE). Ordering of the e-vector is decided
6217aaeacdcSjeremylt                    by the backend.
622be9261b7Sjeremylt   @param request Request or CEED_REQUEST_IMMEDIATE
623be9261b7Sjeremylt 
624be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
625be9261b7Sjeremylt 
626*7a982d89SJeremy L. Thompson   @ref Backend
627be9261b7Sjeremylt **/
628be9261b7Sjeremylt int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block,
629a8d32208Sjeremylt                                   CeedTransposeMode tmode, CeedVector u,
630a8d32208Sjeremylt                                   CeedVector ru, CeedRequest *request) {
631be9261b7Sjeremylt   CeedInt m,n;
632be9261b7Sjeremylt   int ierr;
633be9261b7Sjeremylt 
634be9261b7Sjeremylt   if (tmode == CEED_NOTRANSPOSE) {
635be9261b7Sjeremylt     m = rstr->blksize * rstr->elemsize * rstr->ncomp;
6368795c945Sjeremylt     n = rstr->nnodes * rstr->ncomp;
637be9261b7Sjeremylt   } else {
6388795c945Sjeremylt     m = rstr->nnodes * rstr->ncomp;
639be9261b7Sjeremylt     n = rstr->blksize * rstr->elemsize * rstr->ncomp;
640be9261b7Sjeremylt   }
641be9261b7Sjeremylt   if (n != u->length)
642c042f62fSJeremy L Thompson     // LCOV_EXCL_START
6431d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Input vector size %d not compatible with "
6441d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
645c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
646a8d32208Sjeremylt   if (m != ru->length)
647c042f62fSJeremy L Thompson     // LCOV_EXCL_START
6481d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Output vector size %d not compatible with "
649a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
650c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
651be9261b7Sjeremylt   if (rstr->blksize*block > rstr->nelem)
652c042f62fSJeremy L Thompson     // LCOV_EXCL_START
6531d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Cannot retrieve block %d, element %d > "
6541d102b48SJeremy L Thompson                      "total elements %d", block, rstr->blksize*block,
6551d102b48SJeremy L Thompson                      rstr->nelem);
656c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
657074cb416Sjeremylt   ierr = rstr->ApplyBlock(rstr, block, tmode, u, ru, request);
658be9261b7Sjeremylt   CeedChk(ierr);
659be9261b7Sjeremylt 
660be9261b7Sjeremylt   return 0;
661be9261b7Sjeremylt }
662be9261b7Sjeremylt 
663be9261b7Sjeremylt /**
664d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
6651469ee4dSjeremylt 
6661469ee4dSjeremylt   @param rstr             CeedElemRestriction
667b9c05c73SJed Brown   @param[out] mult        Vector to store multiplicity (of size nnodes*ncomp)
6681469ee4dSjeremylt 
6691469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
6701469ee4dSjeremylt 
671*7a982d89SJeremy L. Thompson   @ref User
6721469ee4dSjeremylt **/
6731469ee4dSjeremylt int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr,
6741469ee4dSjeremylt                                        CeedVector mult) {
6751469ee4dSjeremylt   int ierr;
6761469ee4dSjeremylt   CeedVector evec;
6771469ee4dSjeremylt 
6781469ee4dSjeremylt   // Create and set evec
6791469ee4dSjeremylt   ierr = CeedElemRestrictionCreateVector(rstr, NULL, &evec); CeedChk(ierr);
6801469ee4dSjeremylt   ierr = CeedVectorSetValue(evec, 1.0); CeedChk(ierr);
681fa9eac48SJed Brown   ierr = CeedVectorSetValue(mult, 0.0); CeedChk(ierr);
6821469ee4dSjeremylt 
6831469ee4dSjeremylt   // Apply to get multiplicity
684a8d32208Sjeremylt   ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, evec, mult,
685efc78312Sjeremylt                                   CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
6861469ee4dSjeremylt 
6871469ee4dSjeremylt   // Cleanup
6881469ee4dSjeremylt   ierr = CeedVectorDestroy(&evec); CeedChk(ierr);
6891469ee4dSjeremylt 
6901469ee4dSjeremylt   return 0;
6911469ee4dSjeremylt }
6921469ee4dSjeremylt 
6931469ee4dSjeremylt /**
6944ce2993fSjeremylt 
6957509a596Sjeremylt   @brief Get the strides of a strided CeedElemRestriction
6967509a596Sjeremylt 
6977509a596Sjeremylt   @param rstr             CeedElemRestriction
6987509a596Sjeremylt   @param[out] strides     Variable to store strides array
6997509a596Sjeremylt 
7007509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
7017509a596Sjeremylt 
702*7a982d89SJeremy L. Thompson   @ref Backend
7037509a596Sjeremylt **/
7047509a596Sjeremylt int CeedElemRestrictionGetStrides(CeedElemRestriction rstr,
7057509a596Sjeremylt                                   CeedInt (*strides)[3]) {
7067509a596Sjeremylt   if (!rstr->strides)
7077509a596Sjeremylt     // LCOV_EXCL_START
7087509a596Sjeremylt     return CeedError(rstr->ceed, 1, "ElemRestriction has no stride data");
7097509a596Sjeremylt   // LCOV_EXCL_STOP
7107509a596Sjeremylt 
7117509a596Sjeremylt   for (int i = 0; i<3; i++)
7127509a596Sjeremylt     (*strides)[i] = rstr->strides[i];
7137509a596Sjeremylt   return 0;
7147509a596Sjeremylt }
7157509a596Sjeremylt 
7167509a596Sjeremylt /**
717523b8ea0Sjeremylt   @brief Get the backend stride status of a CeedElemRestriction
718523b8ea0Sjeremylt 
719523b8ea0Sjeremylt   @param rstr             CeedElemRestriction
720523b8ea0Sjeremylt   @param[out] bool        Variable to store stride status
721523b8ea0Sjeremylt 
722523b8ea0Sjeremylt   @return An error code: 0 - success, otherwise - failure
723523b8ea0Sjeremylt 
724*7a982d89SJeremy L. Thompson   @ref Backend
725523b8ea0Sjeremylt **/
726523b8ea0Sjeremylt int CeedElemRestrictionGetBackendStridesStatus(CeedElemRestriction rstr,
727523b8ea0Sjeremylt     bool *status) {
728523b8ea0Sjeremylt   if (!rstr->strides)
729523b8ea0Sjeremylt     // LCOV_EXCL_START
730523b8ea0Sjeremylt     return CeedError(rstr->ceed, 1, "ElemRestriction has no stride data");
731523b8ea0Sjeremylt   // LCOV_EXCL_STOP
732523b8ea0Sjeremylt 
733523b8ea0Sjeremylt   *status = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) &&
734523b8ea0Sjeremylt              (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
735523b8ea0Sjeremylt              (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
736523b8ea0Sjeremylt   return 0;
737523b8ea0Sjeremylt }
738523b8ea0Sjeremylt 
739523b8ea0Sjeremylt /**
740f02ca4a2SJed Brown   @brief View a CeedElemRestriction
741f02ca4a2SJed Brown 
742f02ca4a2SJed Brown   @param[in] rstr    CeedElemRestriction to view
743f02ca4a2SJed Brown   @param[in] stream  Stream to write; typically stdout/stderr or a file
744f02ca4a2SJed Brown 
745f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
746f02ca4a2SJed Brown 
747*7a982d89SJeremy L. Thompson   @ref User
748f02ca4a2SJed Brown **/
749f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
7507509a596Sjeremylt   char stridesstr[500];
7517509a596Sjeremylt   if (rstr->strides)
7527509a596Sjeremylt     sprintf(stridesstr, "[%d, %d, %d]", rstr->strides[0], rstr->strides[1],
7537509a596Sjeremylt             rstr->strides[2]);
7547509a596Sjeremylt 
7550036de2cSjeremylt   fprintf(stream, "%sCeedElemRestriction from (%d, %d) to %d elements with %d "
7560036de2cSjeremylt           "nodes each and %s %s\n", rstr->blksize > 1 ? "Blocked " : "",
7570036de2cSjeremylt           rstr->nnodes, rstr->ncomp, rstr->nelem, rstr->elemsize,
7580036de2cSjeremylt           rstr->strides ? "strides" : "L-vector components",
7597509a596Sjeremylt           rstr->strides ? stridesstr : CeedInterlaceModes[rstr->imode]);
760f02ca4a2SJed Brown   return 0;
761f02ca4a2SJed Brown }
762f02ca4a2SJed Brown 
763f02ca4a2SJed Brown /**
764b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
765b11c1e72Sjeremylt 
7664ce2993fSjeremylt   @param rstr  CeedElemRestriction to destroy
767b11c1e72Sjeremylt 
768b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
769dfdf5a53Sjeremylt 
770*7a982d89SJeremy L. Thompson   @ref User
771b11c1e72Sjeremylt **/
7724ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
773d7b241e6Sjeremylt   int ierr;
774d7b241e6Sjeremylt 
7751d102b48SJeremy L Thompson   if (!*rstr || --(*rstr)->refcount > 0)
7761d102b48SJeremy L Thompson     return 0;
7774ce2993fSjeremylt   if ((*rstr)->Destroy) {
7784ce2993fSjeremylt     ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr);
779d7b241e6Sjeremylt   }
7807509a596Sjeremylt   ierr = CeedFree(&(*rstr)->strides); CeedChk(ierr);
7814ce2993fSjeremylt   ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr);
7824ce2993fSjeremylt   ierr = CeedFree(rstr); CeedChk(ierr);
783d7b241e6Sjeremylt   return 0;
784d7b241e6Sjeremylt }
785d7b241e6Sjeremylt 
786d7b241e6Sjeremylt /// @}
787