xref: /libCEED/interface/ceed-elemrestriction.c (revision 61dbc9d25335c1a7855bdb901ed4d560d51eee1f)
1d7b241e6Sjeremylt // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2d7b241e6Sjeremylt // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3d7b241e6Sjeremylt // reserved. See files LICENSE and NOTICE for details.
4d7b241e6Sjeremylt //
5d7b241e6Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software
6d7b241e6Sjeremylt // libraries and APIs for efficient high-order finite element and spectral
7d7b241e6Sjeremylt // element discretizations for exascale applications. For more information and
8d7b241e6Sjeremylt // source code availability see http://github.com/ceed.
9d7b241e6Sjeremylt //
10d7b241e6Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11d7b241e6Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office
12d7b241e6Sjeremylt // of Science and the National Nuclear Security Administration) responsible for
13d7b241e6Sjeremylt // the planning and preparation of a capable exascale ecosystem, including
14d7b241e6Sjeremylt // software, applications, hardware, advanced system engineering and early
15d7b241e6Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative.
16d7b241e6Sjeremylt 
17d7b241e6Sjeremylt #include <ceed-impl.h>
18d863ab9bSjeremylt #include <ceed-backend.h>
19d7b241e6Sjeremylt 
20d7b241e6Sjeremylt /// @file
21d7b241e6Sjeremylt /// Implementation of public CeedElemRestriction interfaces
22d7b241e6Sjeremylt ///
23dfdf5a53Sjeremylt /// @addtogroup CeedElemRestriction
24d7b241e6Sjeremylt /// @{
25d7b241e6Sjeremylt 
26d7b241e6Sjeremylt /**
27b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
28d7b241e6Sjeremylt 
29b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
30*61dbc9d2Sjeremylt   @param imode      Ordering of the ncomp components, i.e. it specifies
31a8d32208Sjeremylt                       the ordering of the components of the L-vector used
32*61dbc9d2Sjeremylt                       by this CeedElemRestriction. CEED_NONINTERLACED indicates
33*61dbc9d2Sjeremylt                       the component is the outermost index and CEED_INTERLACED
34a8d32208Sjeremylt                       indicates the component is the innermost index in
35a8d32208Sjeremylt                       ordering of the L-vector.
36b11c1e72Sjeremylt   @param nelem      Number of elements described in the @a indices array
37b11c1e72Sjeremylt   @param elemsize   Size (number of "nodes") per element
388795c945Sjeremylt   @param nnodes     The number of nodes in the L-vector. The input CeedVector
398795c945Sjeremylt                       to which the restriction will be applied is of size
408795c945Sjeremylt                       @a nnodes * @a ncomp. This size may include data
41d7b241e6Sjeremylt                       used by other CeedElemRestriction objects describing
42d7b241e6Sjeremylt                       different types of elements.
43b11c1e72Sjeremylt   @param ncomp      Number of field components per interpolation node
4495bb1877Svaleriabarra                       (1 for scalar fields)
45b11c1e72Sjeremylt   @param mtype      Memory type of the @a indices array, see CeedMemType
46b11c1e72Sjeremylt   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
478795c945Sjeremylt   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
488795c945Sjeremylt                       ordered list of the indices (into the input CeedVector)
498795c945Sjeremylt                       for the unknowns corresponding to element i, where
5034138859Sjeremylt                       0 <= i < @a nelem. All indices must be in the range
5123e8ed12Sjeremylt                       [0, @a nnodes - 1].
524ce2993fSjeremylt   @param[out] rstr  Address of the variable where the newly created
53b11c1e72Sjeremylt                       CeedElemRestriction will be stored
54d7b241e6Sjeremylt 
55b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
56dfdf5a53Sjeremylt 
57dfdf5a53Sjeremylt   @ref Basic
58b11c1e72Sjeremylt **/
59*61dbc9d2Sjeremylt int CeedElemRestrictionCreate(Ceed ceed,  CeedInterlaceMode imode,
60*61dbc9d2Sjeremylt                               CeedInt nelem,
61*61dbc9d2Sjeremylt                               CeedInt elemsize, CeedInt nnodes, CeedInt ncomp,
62*61dbc9d2Sjeremylt                               CeedMemType mtype, CeedCopyMode cmode,
63*61dbc9d2Sjeremylt                               const CeedInt *indices,
644ce2993fSjeremylt                               CeedElemRestriction *rstr) {
65d7b241e6Sjeremylt   int ierr;
66d7b241e6Sjeremylt 
675fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
685fe0d4faSjeremylt     Ceed delegate;
69aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
70aefd8378Sjeremylt     CeedChk(ierr);
715fe0d4faSjeremylt 
725fe0d4faSjeremylt     if (!delegate)
73c042f62fSJeremy L Thompson       // LCOV_EXCL_START
74d7b241e6Sjeremylt       return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
75c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
765fe0d4faSjeremylt 
77*61dbc9d2Sjeremylt     ierr = CeedElemRestrictionCreate(delegate, imode, nelem, elemsize,
788795c945Sjeremylt                                      nnodes, ncomp, mtype, cmode,
794ce2993fSjeremylt                                      indices, rstr); CeedChk(ierr);
805fe0d4faSjeremylt     return 0;
815fe0d4faSjeremylt   }
825fe0d4faSjeremylt 
834ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
844ce2993fSjeremylt   (*rstr)->ceed = ceed;
85d7b241e6Sjeremylt   ceed->refcount++;
864ce2993fSjeremylt   (*rstr)->refcount = 1;
87*61dbc9d2Sjeremylt   (*rstr)->imode = imode;
884ce2993fSjeremylt   (*rstr)->nelem = nelem;
894ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
908795c945Sjeremylt   (*rstr)->nnodes = nnodes;
914ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
924ce2993fSjeremylt   (*rstr)->nblk = nelem;
934ce2993fSjeremylt   (*rstr)->blksize = 1;
944ce2993fSjeremylt   ierr = ceed->ElemRestrictionCreate(mtype, cmode, indices, *rstr); CeedChk(ierr);
95d7b241e6Sjeremylt   return 0;
96d7b241e6Sjeremylt }
97d7b241e6Sjeremylt 
98d7b241e6Sjeremylt /**
99b11c1e72Sjeremylt   @brief Create an identity CeedElemRestriction
100d7b241e6Sjeremylt 
101b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
102*61dbc9d2Sjeremylt   @param imode      Ordering of the ncomp components, i.e. it specifies
103a8d32208Sjeremylt                       the ordering of the components of the L-vector used
104*61dbc9d2Sjeremylt                       by this CeedElemRestriction. CEED_NONINTERLACED indicates
105*61dbc9d2Sjeremylt                       the component is the outermost index and CEED_INTERLACED
106a8d32208Sjeremylt                       indicates the component is the innermost index in
107a8d32208Sjeremylt                       ordering of the L-vector.
108b11c1e72Sjeremylt   @param nelem      Number of elements described in the @a indices array
109b11c1e72Sjeremylt   @param elemsize   Size (number of "nodes") per element
1108795c945Sjeremylt   @param nnodes     The number of nodes in the L-vector. The input CeedVector
1118795c945Sjeremylt                       to which the restriction will be applied is of size
1128795c945Sjeremylt                       @a nnodes * @a ncomp. This size may include data
113d7b241e6Sjeremylt                       used by other CeedElemRestriction objects describing
1148795c945Sjeremylt                       different types of elements.
115b11c1e72Sjeremylt   @param ncomp      Number of field components per interpolation node
11695bb1877Svaleriabarra                       (1 for scalar fields)
1174ce2993fSjeremylt   @param rstr       Address of the variable where the newly created
118b11c1e72Sjeremylt                       CeedElemRestriction will be stored
119d7b241e6Sjeremylt 
120b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
121dfdf5a53Sjeremylt 
122dfdf5a53Sjeremylt   @ref Basic
123b11c1e72Sjeremylt **/
124*61dbc9d2Sjeremylt int CeedElemRestrictionCreateIdentity(Ceed ceed,  CeedInterlaceMode imode,
125a8d32208Sjeremylt                                       CeedInt nelem, CeedInt elemsize,
126a8d32208Sjeremylt                                       CeedInt nnodes, CeedInt ncomp,
127f90c8643Sjeremylt                                       CeedElemRestriction *rstr) {
128d7b241e6Sjeremylt   int ierr;
129d7b241e6Sjeremylt 
1305fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
1315fe0d4faSjeremylt     Ceed delegate;
132aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
133aefd8378Sjeremylt     CeedChk(ierr);
1345fe0d4faSjeremylt 
1355fe0d4faSjeremylt     if (!delegate)
136c042f62fSJeremy L Thompson       // LCOV_EXCL_START
1371d102b48SJeremy L Thompson       return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
138c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
1395fe0d4faSjeremylt 
140*61dbc9d2Sjeremylt     ierr = CeedElemRestrictionCreateIdentity(delegate, imode, nelem, elemsize,
1418795c945Sjeremylt            nnodes, ncomp, rstr); CeedChk(ierr);
1425fe0d4faSjeremylt     return 0;
1435fe0d4faSjeremylt   }
1445fe0d4faSjeremylt 
1454ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
1464ce2993fSjeremylt   (*rstr)->ceed = ceed;
147d7b241e6Sjeremylt   ceed->refcount++;
1484ce2993fSjeremylt   (*rstr)->refcount = 1;
149*61dbc9d2Sjeremylt   (*rstr)->imode = imode;
1504ce2993fSjeremylt   (*rstr)->nelem = nelem;
1514ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
1528795c945Sjeremylt   (*rstr)->nnodes = nnodes;
1534ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
1544ce2993fSjeremylt   (*rstr)->nblk = nelem;
1554ce2993fSjeremylt   (*rstr)->blksize = 1;
1561dfeef1dSjeremylt   ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL,
1571dfeef1dSjeremylt                                      *rstr);
1584b8bea3bSJed Brown   CeedChk(ierr);
159d7b241e6Sjeremylt   return 0;
160d7b241e6Sjeremylt }
161d7b241e6Sjeremylt 
162d7b241e6Sjeremylt /**
163b11c1e72Sjeremylt   @brief Permute and pad indices for a blocked restriction
164d7b241e6Sjeremylt 
1658795c945Sjeremylt   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
1668795c945Sjeremylt                       ordered list of the indices (into the input CeedVector)
1678795c945Sjeremylt                       for the unknowns corresponding to element i, where
16834138859Sjeremylt                       0 <= i < @a nelem. All indices must be in the range
1698795c945Sjeremylt                       [0, @a nnodes).
170ecf6354eSJed Brown   @param blkindices Array of permuted and padded indices of
171ecf6354eSJed Brown                       shape [@a nblk, @a elemsize, @a blksize].
172d7b241e6Sjeremylt   @param nblk       Number of blocks
173d7b241e6Sjeremylt   @param nelem      Number of elements
174d7b241e6Sjeremylt   @param blksize    Number of elements in a block
175d7b241e6Sjeremylt   @param elemsize   Size of each element
176d7b241e6Sjeremylt 
177b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
178b11c1e72Sjeremylt 
179dfdf5a53Sjeremylt   @ref Utility
180b11c1e72Sjeremylt **/
181dfdf5a53Sjeremylt int CeedPermutePadIndices(const CeedInt *indices, CeedInt *blkindices,
182692c2638Sjeremylt                           CeedInt nblk, CeedInt nelem, CeedInt blksize,
183692c2638Sjeremylt                           CeedInt elemsize) {
184d7b241e6Sjeremylt   for (CeedInt e = 0; e < nblk*blksize; e+=blksize)
185d7b241e6Sjeremylt     for (int j = 0; j < blksize; j++)
186d7b241e6Sjeremylt       for (int k = 0; k < elemsize; k++)
187d7b241e6Sjeremylt         blkindices[e*elemsize + k*blksize + j]
188d7b241e6Sjeremylt           = indices[CeedIntMin(e+j,nelem-1)*elemsize + k];
189dfdf5a53Sjeremylt   return 0;
190d7b241e6Sjeremylt }
191d7b241e6Sjeremylt 
192d7b241e6Sjeremylt /**
193b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
194d7b241e6Sjeremylt 
195d7b241e6Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created.
196*61dbc9d2Sjeremylt   @param imode      Ordering of the ncomp components, i.e. it specifies
197a8d32208Sjeremylt                       the ordering of the components of the L-vector used
198*61dbc9d2Sjeremylt                       by this CeedElemRestriction. CEED_NONINTERLACED indicates
199*61dbc9d2Sjeremylt                       the component is the outermost index and CEED_INTERLACED
200a8d32208Sjeremylt                       indicates the component is the innermost index in
201a8d32208Sjeremylt                       ordering of the L-vector.
202d7b241e6Sjeremylt   @param nelem      Number of elements described in the @a indices array.
203b11c1e72Sjeremylt   @param elemsize   Size (number of unknowns) per element
204b11c1e72Sjeremylt   @param blksize    Number of elements in a block
2058795c945Sjeremylt   @param nnodes     The number of nodes in the L-vector. The input CeedVector
2068795c945Sjeremylt                       to which the restriction will be applied is of size
2078795c945Sjeremylt                       @a nnodes * @a ncomp. This size may include data
208d7b241e6Sjeremylt                       used by other CeedElemRestriction objects describing
209d7b241e6Sjeremylt                       different types of elements.
21095bb1877Svaleriabarra   @param ncomp      Number of field components per interpolation node
21195bb1877Svaleriabarra                       (1 for scalar fields)
212b11c1e72Sjeremylt   @param mtype      Memory type of the @a indices array, see CeedMemType
213b11c1e72Sjeremylt   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
2148795c945Sjeremylt   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
2158795c945Sjeremylt                       ordered list of the indices (into the input CeedVector)
2168795c945Sjeremylt                       for the unknowns corresponding to element i, where
21734138859Sjeremylt                       0 <= i < @a nelem. All indices must be in the range
2188795c945Sjeremylt                       [0, @a nnodes). The backend will permute and pad this
2198795c945Sjeremylt                       array to the desired ordering for the blocksize, which is
2208795c945Sjeremylt                       typically given by the backend. The default reordering is
2218795c945Sjeremylt                       to interlace elements.
2224ce2993fSjeremylt   @param rstr       Address of the variable where the newly created
223b11c1e72Sjeremylt                       CeedElemRestriction will be stored
224d7b241e6Sjeremylt 
225b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
226dfdf5a53Sjeremylt 
227dfdf5a53Sjeremylt   @ref Advanced
228b11c1e72Sjeremylt  **/
229*61dbc9d2Sjeremylt int CeedElemRestrictionCreateBlocked(Ceed ceed,  CeedInterlaceMode imode,
230a8d32208Sjeremylt                                      CeedInt nelem, CeedInt elemsize,
2318795c945Sjeremylt                                      CeedInt blksize, CeedInt nnodes,
2328795c945Sjeremylt                                      CeedInt ncomp, CeedMemType mtype,
2338795c945Sjeremylt                                      CeedCopyMode cmode, const CeedInt *indices,
2344ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
235d7b241e6Sjeremylt   int ierr;
236d7b241e6Sjeremylt   CeedInt *blkindices;
237d7b241e6Sjeremylt   CeedInt nblk = (nelem / blksize) + !!(nelem % blksize);
238d7b241e6Sjeremylt 
2395fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
2405fe0d4faSjeremylt     Ceed delegate;
241aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
242aefd8378Sjeremylt     CeedChk(ierr);
2435fe0d4faSjeremylt 
2445fe0d4faSjeremylt     if (!delegate)
245c042f62fSJeremy L Thompson       // LCOV_EXCL_START
2461d102b48SJeremy L Thompson       return CeedError(ceed, 1, "Backend does not support "
2471d102b48SJeremy L Thompson                        "ElemRestrictionCreateBlocked");
248c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
2495fe0d4faSjeremylt 
250*61dbc9d2Sjeremylt     ierr = CeedElemRestrictionCreateBlocked(delegate, imode, nelem, elemsize,
2518795c945Sjeremylt                                             blksize, nnodes, ncomp, mtype, cmode,
2524ce2993fSjeremylt                                             indices, rstr); CeedChk(ierr);
2535fe0d4faSjeremylt     return 0;
2545fe0d4faSjeremylt   }
255d7b241e6Sjeremylt 
2564ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
257d7b241e6Sjeremylt 
258d7b241e6Sjeremylt   if (indices) {
259de686571SJeremy L Thompson     ierr = CeedCalloc(nblk*blksize*elemsize, &blkindices); CeedChk(ierr);
2604b8bea3bSJed Brown     ierr = CeedPermutePadIndices(indices, blkindices, nblk, nelem, blksize,
2614b8bea3bSJed Brown                                  elemsize);
262dfdf5a53Sjeremylt     CeedChk(ierr);
263d7b241e6Sjeremylt   } else {
264d7b241e6Sjeremylt     blkindices = NULL;
265d7b241e6Sjeremylt   }
266d7b241e6Sjeremylt 
2674ce2993fSjeremylt   (*rstr)->ceed = ceed;
268d7b241e6Sjeremylt   ceed->refcount++;
2694ce2993fSjeremylt   (*rstr)->refcount = 1;
270*61dbc9d2Sjeremylt   (*rstr)->imode = imode;
2714ce2993fSjeremylt   (*rstr)->nelem = nelem;
2724ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
2738795c945Sjeremylt   (*rstr)->nnodes = nnodes;
2744ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
2754ce2993fSjeremylt   (*rstr)->nblk = nblk;
2764ce2993fSjeremylt   (*rstr)->blksize = blksize;
277667bc5fcSjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
2787f823360Sjeremylt          (const CeedInt *) blkindices, *rstr); CeedChk(ierr);
279d7b241e6Sjeremylt 
2801d102b48SJeremy L Thompson   if (cmode == CEED_OWN_POINTER) {
281d7b241e6Sjeremylt     ierr = CeedFree(&indices); CeedChk(ierr);
2821d102b48SJeremy L Thompson   }
283d7b241e6Sjeremylt 
284d7b241e6Sjeremylt   return 0;
285d7b241e6Sjeremylt }
286d7b241e6Sjeremylt 
287b11c1e72Sjeremylt /**
288b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
289b11c1e72Sjeremylt 
2904ce2993fSjeremylt   @param rstr  CeedElemRestriction
291b11c1e72Sjeremylt   @param lvec  The address of the L-vector to be created, or NULL
292b11c1e72Sjeremylt   @param evec  The address of the E-vector to be created, or NULL
293b11c1e72Sjeremylt 
294b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
295dfdf5a53Sjeremylt 
296dfdf5a53Sjeremylt   @ref Advanced
297b11c1e72Sjeremylt **/
2984ce2993fSjeremylt int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *lvec,
299d7b241e6Sjeremylt                                     CeedVector *evec) {
300d7b241e6Sjeremylt   int ierr;
301d7b241e6Sjeremylt   CeedInt n, m;
3028795c945Sjeremylt   m = rstr->nnodes * rstr->ncomp;
3034ce2993fSjeremylt   n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
304d7b241e6Sjeremylt   if (lvec) {
3054ce2993fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, m, lvec); CeedChk(ierr);
306d7b241e6Sjeremylt   }
307d7b241e6Sjeremylt   if (evec) {
3084ce2993fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, n, evec); CeedChk(ierr);
309d7b241e6Sjeremylt   }
310d7b241e6Sjeremylt   return 0;
311d7b241e6Sjeremylt }
312d7b241e6Sjeremylt 
313d7b241e6Sjeremylt /**
314d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
315d7b241e6Sjeremylt 
3164ce2993fSjeremylt   @param rstr    CeedElemRestriction
317d7b241e6Sjeremylt   @param tmode   Apply restriction or transpose
3187aaeacdcSjeremylt   @param u       Input vector (of shape [@a nnodes, @a ncomp] when
319*61dbc9d2Sjeremylt                    tmode=CEED_NOTRANSPOSE, imode=CEED_INTERLACED)
320a8d32208Sjeremylt   @param ru      Output vector (of shape [@a nelem * @a elemsize] when
3217aaeacdcSjeremylt                    tmode=CEED_NOTRANSPOSE). Ordering of the e-vector is decided
3227aaeacdcSjeremylt                    by the backend.
323d7b241e6Sjeremylt   @param request Request or CEED_REQUEST_IMMEDIATE
324b11c1e72Sjeremylt 
325b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
326dfdf5a53Sjeremylt 
327dfdf5a53Sjeremylt   @ref Advanced
328b11c1e72Sjeremylt **/
3294ce2993fSjeremylt int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode tmode,
330a8d32208Sjeremylt                              CeedVector u, CeedVector ru,
331a8d32208Sjeremylt                              CeedRequest *request) {
332d7b241e6Sjeremylt   CeedInt m,n;
333d7b241e6Sjeremylt   int ierr;
334d7b241e6Sjeremylt 
335d7b241e6Sjeremylt   if (tmode == CEED_NOTRANSPOSE) {
3364ce2993fSjeremylt     m = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
3378795c945Sjeremylt     n = rstr->nnodes * rstr->ncomp;
338d7b241e6Sjeremylt   } else {
3398795c945Sjeremylt     m = rstr->nnodes * rstr->ncomp;
3404ce2993fSjeremylt     n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
341d7b241e6Sjeremylt   }
342d7b241e6Sjeremylt   if (n != u->length)
343c042f62fSJeremy L Thompson     // LCOV_EXCL_START
3441d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Input vector size %d not compatible with "
3451d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
346c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
347a8d32208Sjeremylt   if (m != ru->length)
348c042f62fSJeremy L Thompson     // LCOV_EXCL_START
3491d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Output vector size %d not compatible with "
350a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
351c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
352074cb416Sjeremylt   ierr = rstr->Apply(rstr, tmode, u, ru, request); CeedChk(ierr);
353d7b241e6Sjeremylt 
354d7b241e6Sjeremylt   return 0;
355d7b241e6Sjeremylt }
356d7b241e6Sjeremylt 
357d7b241e6Sjeremylt /**
358d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
359be9261b7Sjeremylt 
360be9261b7Sjeremylt   @param rstr    CeedElemRestriction
3611f37b403Sjeremylt   @param block   Block number to restrict to/from, i.e. block=0 will handle
3621f37b403Sjeremylt                    elements [0 : blksize] and block=3 will handle elements
3631f37b403Sjeremylt                    [3*blksize : 4*blksize]
364be9261b7Sjeremylt   @param tmode   Apply restriction or transpose
3657aaeacdcSjeremylt   @param u       Input vector (of shape [@a nnodes, @a ncomp] when
366*61dbc9d2Sjeremylt                    tmode=CEED_NOTRANSPOSE, imode=CEED_INTERLACED)
367a8d32208Sjeremylt   @param ru      Output vector (of shape [@a blksize * @a elemsize] when
3687aaeacdcSjeremylt                    tmode=CEED_NOTRANSPOSE). Ordering of the e-vector is decided
3697aaeacdcSjeremylt                    by the backend.
370be9261b7Sjeremylt   @param request Request or CEED_REQUEST_IMMEDIATE
371be9261b7Sjeremylt 
372be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
373be9261b7Sjeremylt 
374be9261b7Sjeremylt   @ref Advanced
375be9261b7Sjeremylt **/
376be9261b7Sjeremylt int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block,
377a8d32208Sjeremylt                                   CeedTransposeMode tmode, CeedVector u,
378a8d32208Sjeremylt                                   CeedVector ru, CeedRequest *request) {
379be9261b7Sjeremylt   CeedInt m,n;
380be9261b7Sjeremylt   int ierr;
381be9261b7Sjeremylt 
382be9261b7Sjeremylt   if (tmode == CEED_NOTRANSPOSE) {
383be9261b7Sjeremylt     m = rstr->blksize * rstr->elemsize * rstr->ncomp;
3848795c945Sjeremylt     n = rstr->nnodes * rstr->ncomp;
385be9261b7Sjeremylt   } else {
3868795c945Sjeremylt     m = rstr->nnodes * rstr->ncomp;
387be9261b7Sjeremylt     n = rstr->blksize * rstr->elemsize * rstr->ncomp;
388be9261b7Sjeremylt   }
389be9261b7Sjeremylt   if (n != u->length)
390c042f62fSJeremy L Thompson     // LCOV_EXCL_START
3911d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Input vector size %d not compatible with "
3921d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
393c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
394a8d32208Sjeremylt   if (m != ru->length)
395c042f62fSJeremy L Thompson     // LCOV_EXCL_START
3961d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Output vector size %d not compatible with "
397a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
398c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
399be9261b7Sjeremylt   if (rstr->blksize*block > rstr->nelem)
400c042f62fSJeremy L Thompson     // LCOV_EXCL_START
4011d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Cannot retrieve block %d, element %d > "
4021d102b48SJeremy L Thompson                      "total elements %d", block, rstr->blksize*block,
4031d102b48SJeremy L Thompson                      rstr->nelem);
404c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
405074cb416Sjeremylt   ierr = rstr->ApplyBlock(rstr, block, tmode, u, ru, request);
406be9261b7Sjeremylt   CeedChk(ierr);
407be9261b7Sjeremylt 
408be9261b7Sjeremylt   return 0;
409be9261b7Sjeremylt }
410be9261b7Sjeremylt 
411be9261b7Sjeremylt /**
412d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
4131469ee4dSjeremylt 
4141469ee4dSjeremylt   @param rstr             CeedElemRestriction
415d9e1f99aSValeria Barra   @param[out] mult        Vector to store multiplicity (of size nnodes)
4161469ee4dSjeremylt 
4171469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
4181469ee4dSjeremylt 
4191469ee4dSjeremylt   @ref Advanced
4201469ee4dSjeremylt **/
4211469ee4dSjeremylt int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr,
4221469ee4dSjeremylt                                        CeedVector mult) {
4231469ee4dSjeremylt   int ierr;
4241469ee4dSjeremylt   CeedVector evec;
4251469ee4dSjeremylt 
4261469ee4dSjeremylt   // Create and set evec
4271469ee4dSjeremylt   ierr = CeedElemRestrictionCreateVector(rstr, NULL, &evec); CeedChk(ierr);
4281469ee4dSjeremylt   ierr = CeedVectorSetValue(evec, 1.0); CeedChk(ierr);
4291469ee4dSjeremylt 
4301469ee4dSjeremylt   // Apply to get multiplicity
431a8d32208Sjeremylt   ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, evec, mult,
432efc78312Sjeremylt                                   CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
4331469ee4dSjeremylt 
4341469ee4dSjeremylt   // Cleanup
4351469ee4dSjeremylt   ierr = CeedVectorDestroy(&evec); CeedChk(ierr);
4361469ee4dSjeremylt 
4371469ee4dSjeremylt   return 0;
4381469ee4dSjeremylt }
4391469ee4dSjeremylt 
4401469ee4dSjeremylt /**
4414ce2993fSjeremylt   @brief Get the Ceed associated with a CeedElemRestriction
4424ce2993fSjeremylt 
4434ce2993fSjeremylt   @param rstr             CeedElemRestriction
4444ce2993fSjeremylt   @param[out] ceed        Variable to store Ceed
4454ce2993fSjeremylt 
4464ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
4474ce2993fSjeremylt 
44823617272Sjeremylt   @ref Advanced
4494ce2993fSjeremylt **/
4504ce2993fSjeremylt int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
4514ce2993fSjeremylt   *ceed = rstr->ceed;
4524ce2993fSjeremylt   return 0;
4534ce2993fSjeremylt }
4544ce2993fSjeremylt 
4554ce2993fSjeremylt /**
456*61dbc9d2Sjeremylt   @brief Get the L-vector interlaced mode of a CeedElemRestriction
457a8d32208Sjeremylt 
458a8d32208Sjeremylt   @param rstr             CeedElemRestriction
459*61dbc9d2Sjeremylt   @param[out] imode       Variable to store imode
460a8d32208Sjeremylt 
461a8d32208Sjeremylt   @return An error code: 0 - success, otherwise - failure
462a8d32208Sjeremylt 
463a8d32208Sjeremylt   @ref Advanced
464a8d32208Sjeremylt **/
465*61dbc9d2Sjeremylt int CeedElemRestrictionGetIMode(CeedElemRestriction rstr,
466*61dbc9d2Sjeremylt                                 CeedInterlaceMode *imode) {
467*61dbc9d2Sjeremylt   *imode = rstr->imode;
468a8d32208Sjeremylt   return 0;
469a8d32208Sjeremylt }
470a8d32208Sjeremylt 
471a8d32208Sjeremylt /**
472b11c1e72Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
473d7b241e6Sjeremylt 
4744ce2993fSjeremylt   @param rstr             CeedElemRestriction
475288c0443SJeremy L Thompson   @param[out] numelem     Variable to store number of elements
476b11c1e72Sjeremylt 
477b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
478dfdf5a53Sjeremylt 
47923617272Sjeremylt   @ref Advanced
480b11c1e72Sjeremylt **/
4814ce2993fSjeremylt int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
4824ce2993fSjeremylt                                       CeedInt *numelem) {
4834ce2993fSjeremylt   *numelem = rstr->nelem;
4844ce2993fSjeremylt   return 0;
4854ce2993fSjeremylt }
4864ce2993fSjeremylt 
4874ce2993fSjeremylt /**
4884ce2993fSjeremylt   @brief Get the size of elements in the CeedElemRestriction
4894ce2993fSjeremylt 
4904ce2993fSjeremylt   @param rstr             CeedElemRestriction
4914ce2993fSjeremylt   @param[out] elemsize    Variable to store size of elements
4924ce2993fSjeremylt 
4934ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
4944ce2993fSjeremylt 
49523617272Sjeremylt   @ref Advanced
4964ce2993fSjeremylt **/
4974ce2993fSjeremylt int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
4984ce2993fSjeremylt                                       CeedInt *elemsize) {
4994ce2993fSjeremylt   *elemsize = rstr->elemsize;
5004ce2993fSjeremylt   return 0;
5014ce2993fSjeremylt }
5024ce2993fSjeremylt 
5034ce2993fSjeremylt /**
5044ce2993fSjeremylt   @brief Get the number of degrees of freedom in the range of a
5054ce2993fSjeremylt          CeedElemRestriction
5064ce2993fSjeremylt 
5074ce2993fSjeremylt   @param rstr             CeedElemRestriction
5088795c945Sjeremylt   @param[out] numnodes    Variable to store number of nodes
5094ce2993fSjeremylt 
5104ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5114ce2993fSjeremylt 
51223617272Sjeremylt   @ref Advanced
5134ce2993fSjeremylt **/
5148795c945Sjeremylt int CeedElemRestrictionGetNumNodes(CeedElemRestriction rstr,
5158795c945Sjeremylt                                    CeedInt *numnodes) {
5168795c945Sjeremylt   *numnodes = rstr->nnodes;
5174ce2993fSjeremylt   return 0;
5184ce2993fSjeremylt }
5194ce2993fSjeremylt 
5204ce2993fSjeremylt /**
5214ce2993fSjeremylt   @brief Get the number of components in the elements of a
5224ce2993fSjeremylt          CeedElemRestriction
5234ce2993fSjeremylt 
5244ce2993fSjeremylt   @param rstr             CeedElemRestriction
5254ce2993fSjeremylt   @param[out] numcomp     Variable to store number of components
5264ce2993fSjeremylt 
5274ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5284ce2993fSjeremylt 
52923617272Sjeremylt   @ref Advanced
5304ce2993fSjeremylt **/
5314ce2993fSjeremylt int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
5324ce2993fSjeremylt                                         CeedInt *numcomp) {
5334ce2993fSjeremylt   *numcomp = rstr->ncomp;
5344ce2993fSjeremylt   return 0;
5354ce2993fSjeremylt }
5364ce2993fSjeremylt 
5374ce2993fSjeremylt /**
5384ce2993fSjeremylt   @brief Get the number of blocks in a CeedElemRestriction
5394ce2993fSjeremylt 
5404ce2993fSjeremylt   @param rstr             CeedElemRestriction
5414ce2993fSjeremylt   @param[out] numblock    Variable to store number of blocks
5424ce2993fSjeremylt 
5434ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5444ce2993fSjeremylt 
54523617272Sjeremylt   @ref Advanced
5464ce2993fSjeremylt **/
5474ce2993fSjeremylt int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
5484ce2993fSjeremylt                                     CeedInt *numblock) {
5494ce2993fSjeremylt   *numblock = rstr->nblk;
5504ce2993fSjeremylt   return 0;
5514ce2993fSjeremylt }
5524ce2993fSjeremylt 
5534ce2993fSjeremylt /**
5544ce2993fSjeremylt   @brief Get the size of blocks in the CeedElemRestriction
5554ce2993fSjeremylt 
556288c0443SJeremy L Thompson   @param rstr             CeedElemRestriction
5574ce2993fSjeremylt   @param[out] blksize     Variable to store size of blocks
5584ce2993fSjeremylt 
5594ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5604ce2993fSjeremylt 
56123617272Sjeremylt   @ref Advanced
5624ce2993fSjeremylt **/
5634ce2993fSjeremylt int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
5644ce2993fSjeremylt                                     CeedInt *blksize) {
5654ce2993fSjeremylt   *blksize = rstr->blksize;
5664ce2993fSjeremylt   return 0;
5674ce2993fSjeremylt }
5684ce2993fSjeremylt 
5694ce2993fSjeremylt /**
5704ce2993fSjeremylt   @brief Get the backend data of a CeedElemRestriction
5714ce2993fSjeremylt 
572288c0443SJeremy L Thompson   @param rstr             CeedElemRestriction
5734ce2993fSjeremylt   @param[out] data        Variable to store data
5744ce2993fSjeremylt 
5754ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5764ce2993fSjeremylt 
57723617272Sjeremylt   @ref Advanced
5784ce2993fSjeremylt **/
5791d102b48SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void **data) {
5804ce2993fSjeremylt   *data = rstr->data;
581d7b241e6Sjeremylt   return 0;
582d7b241e6Sjeremylt }
583d7b241e6Sjeremylt 
584d7b241e6Sjeremylt /**
585fe2413ffSjeremylt   @brief Set the backend data of a CeedElemRestriction
586fe2413ffSjeremylt 
587288c0443SJeremy L Thompson   @param[out] rstr        CeedElemRestriction
588fe2413ffSjeremylt   @param data             Data to set
589fe2413ffSjeremylt 
590fe2413ffSjeremylt   @return An error code: 0 - success, otherwise - failure
591fe2413ffSjeremylt 
592fe2413ffSjeremylt   @ref Advanced
593fe2413ffSjeremylt **/
5941d102b48SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void **data) {
595fe2413ffSjeremylt   rstr->data = *data;
596fe2413ffSjeremylt   return 0;
597fe2413ffSjeremylt }
598fe2413ffSjeremylt 
599fe2413ffSjeremylt /**
600f02ca4a2SJed Brown   @brief View a CeedElemRestriction
601f02ca4a2SJed Brown 
602f02ca4a2SJed Brown   @param[in] rstr    CeedElemRestriction to view
603f02ca4a2SJed Brown   @param[in] stream  Stream to write; typically stdout/stderr or a file
604f02ca4a2SJed Brown 
605f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
606f02ca4a2SJed Brown 
607f02ca4a2SJed Brown   @ref Utility
608f02ca4a2SJed Brown **/
609f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
6101d102b48SJeremy L Thompson   fprintf(stream, "CeedElemRestriction from (%d, %d) to %d elements with %d "
611*61dbc9d2Sjeremylt           "nodes each and L-vector components %s\n", rstr->nnodes, rstr->ncomp,
612*61dbc9d2Sjeremylt           rstr->nelem, rstr->elemsize, CeedInterlaceModes[rstr->imode]);
613f02ca4a2SJed Brown   return 0;
614f02ca4a2SJed Brown }
615f02ca4a2SJed Brown 
616f02ca4a2SJed Brown /**
617b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
618b11c1e72Sjeremylt 
6194ce2993fSjeremylt   @param rstr  CeedElemRestriction to destroy
620b11c1e72Sjeremylt 
621b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
622dfdf5a53Sjeremylt 
623dfdf5a53Sjeremylt   @ref Basic
624b11c1e72Sjeremylt **/
6254ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
626d7b241e6Sjeremylt   int ierr;
627d7b241e6Sjeremylt 
6281d102b48SJeremy L Thompson   if (!*rstr || --(*rstr)->refcount > 0)
6291d102b48SJeremy L Thompson     return 0;
6304ce2993fSjeremylt   if ((*rstr)->Destroy) {
6314ce2993fSjeremylt     ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr);
632d7b241e6Sjeremylt   }
6334ce2993fSjeremylt   ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr);
6344ce2993fSjeremylt   ierr = CeedFree(rstr); CeedChk(ierr);
635d7b241e6Sjeremylt   return 0;
636d7b241e6Sjeremylt }
637d7b241e6Sjeremylt 
638d7b241e6Sjeremylt /// @}
639