xref: /libCEED/interface/ceed-elemrestriction.c (revision b9c05c73848caa4a8e85dca1ee63c2e7e70143c4)
1d7b241e6Sjeremylt // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2d7b241e6Sjeremylt // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3d7b241e6Sjeremylt // reserved. See files LICENSE and NOTICE for details.
4d7b241e6Sjeremylt //
5d7b241e6Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software
6d7b241e6Sjeremylt // libraries and APIs for efficient high-order finite element and spectral
7d7b241e6Sjeremylt // element discretizations for exascale applications. For more information and
8d7b241e6Sjeremylt // source code availability see http://github.com/ceed.
9d7b241e6Sjeremylt //
10d7b241e6Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11d7b241e6Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office
12d7b241e6Sjeremylt // of Science and the National Nuclear Security Administration) responsible for
13d7b241e6Sjeremylt // the planning and preparation of a capable exascale ecosystem, including
14d7b241e6Sjeremylt // software, applications, hardware, advanced system engineering and early
15d7b241e6Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative.
16d7b241e6Sjeremylt 
17d7b241e6Sjeremylt #include <ceed-impl.h>
18d863ab9bSjeremylt #include <ceed-backend.h>
19d7b241e6Sjeremylt 
20d7b241e6Sjeremylt /// @file
21d7b241e6Sjeremylt /// Implementation of public CeedElemRestriction interfaces
22d7b241e6Sjeremylt ///
23dfdf5a53Sjeremylt /// @addtogroup CeedElemRestriction
24d7b241e6Sjeremylt /// @{
25d7b241e6Sjeremylt 
26d7b241e6Sjeremylt /**
27b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
28d7b241e6Sjeremylt 
29b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
3061dbc9d2Sjeremylt   @param imode      Ordering of the ncomp components, i.e. it specifies
31a8d32208Sjeremylt                       the ordering of the components of the L-vector used
3261dbc9d2Sjeremylt                       by this CeedElemRestriction. CEED_NONINTERLACED indicates
3361dbc9d2Sjeremylt                       the component is the outermost index and CEED_INTERLACED
34a8d32208Sjeremylt                       indicates the component is the innermost index in
35a8d32208Sjeremylt                       ordering of the L-vector.
36b11c1e72Sjeremylt   @param nelem      Number of elements described in the @a indices array
37b11c1e72Sjeremylt   @param elemsize   Size (number of "nodes") per element
388795c945Sjeremylt   @param nnodes     The number of nodes in the L-vector. The input CeedVector
398795c945Sjeremylt                       to which the restriction will be applied is of size
408795c945Sjeremylt                       @a nnodes * @a ncomp. This size may include data
41d7b241e6Sjeremylt                       used by other CeedElemRestriction objects describing
42d7b241e6Sjeremylt                       different types of elements.
43b11c1e72Sjeremylt   @param ncomp      Number of field components per interpolation node
4495bb1877Svaleriabarra                       (1 for scalar fields)
45b11c1e72Sjeremylt   @param mtype      Memory type of the @a indices array, see CeedMemType
46b11c1e72Sjeremylt   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
478795c945Sjeremylt   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
488795c945Sjeremylt                       ordered list of the indices (into the input CeedVector)
498795c945Sjeremylt                       for the unknowns corresponding to element i, where
5034138859Sjeremylt                       0 <= i < @a nelem. All indices must be in the range
5123e8ed12Sjeremylt                       [0, @a nnodes - 1].
524ce2993fSjeremylt   @param[out] rstr  Address of the variable where the newly created
53b11c1e72Sjeremylt                       CeedElemRestriction will be stored
54d7b241e6Sjeremylt 
55b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
56dfdf5a53Sjeremylt 
57dfdf5a53Sjeremylt   @ref Basic
58b11c1e72Sjeremylt **/
5961dbc9d2Sjeremylt int CeedElemRestrictionCreate(Ceed ceed,  CeedInterlaceMode imode,
6061dbc9d2Sjeremylt                               CeedInt nelem,
6161dbc9d2Sjeremylt                               CeedInt elemsize, CeedInt nnodes, CeedInt ncomp,
6261dbc9d2Sjeremylt                               CeedMemType mtype, CeedCopyMode cmode,
6361dbc9d2Sjeremylt                               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 
7761dbc9d2Sjeremylt     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;
8761dbc9d2Sjeremylt   (*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
10261dbc9d2Sjeremylt   @param imode      Ordering of the ncomp components, i.e. it specifies
103a8d32208Sjeremylt                       the ordering of the components of the L-vector used
10461dbc9d2Sjeremylt                       by this CeedElemRestriction. CEED_NONINTERLACED indicates
10561dbc9d2Sjeremylt                       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 **/
12461dbc9d2Sjeremylt 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 
14061dbc9d2Sjeremylt     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;
14961dbc9d2Sjeremylt   (*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.
19661dbc9d2Sjeremylt   @param imode      Ordering of the ncomp components, i.e. it specifies
197a8d32208Sjeremylt                       the ordering of the components of the L-vector used
19861dbc9d2Sjeremylt                       by this CeedElemRestriction. CEED_NONINTERLACED indicates
19961dbc9d2Sjeremylt                       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  **/
22961dbc9d2Sjeremylt 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 
25061dbc9d2Sjeremylt     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;
27061dbc9d2Sjeremylt   (*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
31961dbc9d2Sjeremylt                    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
36661dbc9d2Sjeremylt                    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
415*b9c05c73SJed Brown   @param[out] mult        Vector to store multiplicity (of size nnodes*ncomp)
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);
429fa9eac48SJed Brown   ierr = CeedVectorSetValue(mult, 0.0); CeedChk(ierr);
4301469ee4dSjeremylt 
4311469ee4dSjeremylt   // Apply to get multiplicity
432a8d32208Sjeremylt   ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, evec, mult,
433efc78312Sjeremylt                                   CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
4341469ee4dSjeremylt 
4351469ee4dSjeremylt   // Cleanup
4361469ee4dSjeremylt   ierr = CeedVectorDestroy(&evec); CeedChk(ierr);
4371469ee4dSjeremylt 
4381469ee4dSjeremylt   return 0;
4391469ee4dSjeremylt }
4401469ee4dSjeremylt 
4411469ee4dSjeremylt /**
4424ce2993fSjeremylt   @brief Get the Ceed associated with a CeedElemRestriction
4434ce2993fSjeremylt 
4444ce2993fSjeremylt   @param rstr             CeedElemRestriction
4454ce2993fSjeremylt   @param[out] ceed        Variable to store Ceed
4464ce2993fSjeremylt 
4474ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
4484ce2993fSjeremylt 
44923617272Sjeremylt   @ref Advanced
4504ce2993fSjeremylt **/
4514ce2993fSjeremylt int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
4524ce2993fSjeremylt   *ceed = rstr->ceed;
4534ce2993fSjeremylt   return 0;
4544ce2993fSjeremylt }
4554ce2993fSjeremylt 
4564ce2993fSjeremylt /**
45761dbc9d2Sjeremylt   @brief Get the L-vector interlaced mode of a CeedElemRestriction
458a8d32208Sjeremylt 
459a8d32208Sjeremylt   @param rstr             CeedElemRestriction
46061dbc9d2Sjeremylt   @param[out] imode       Variable to store imode
461a8d32208Sjeremylt 
462a8d32208Sjeremylt   @return An error code: 0 - success, otherwise - failure
463a8d32208Sjeremylt 
464a8d32208Sjeremylt   @ref Advanced
465a8d32208Sjeremylt **/
46661dbc9d2Sjeremylt int CeedElemRestrictionGetIMode(CeedElemRestriction rstr,
46761dbc9d2Sjeremylt                                 CeedInterlaceMode *imode) {
46861dbc9d2Sjeremylt   *imode = rstr->imode;
469a8d32208Sjeremylt   return 0;
470a8d32208Sjeremylt }
471a8d32208Sjeremylt 
472a8d32208Sjeremylt /**
473b11c1e72Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
474d7b241e6Sjeremylt 
4754ce2993fSjeremylt   @param rstr             CeedElemRestriction
476288c0443SJeremy L Thompson   @param[out] numelem     Variable to store number of elements
477b11c1e72Sjeremylt 
478b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
479dfdf5a53Sjeremylt 
48023617272Sjeremylt   @ref Advanced
481b11c1e72Sjeremylt **/
4824ce2993fSjeremylt int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
4834ce2993fSjeremylt                                       CeedInt *numelem) {
4844ce2993fSjeremylt   *numelem = rstr->nelem;
4854ce2993fSjeremylt   return 0;
4864ce2993fSjeremylt }
4874ce2993fSjeremylt 
4884ce2993fSjeremylt /**
4894ce2993fSjeremylt   @brief Get the size of elements in the CeedElemRestriction
4904ce2993fSjeremylt 
4914ce2993fSjeremylt   @param rstr             CeedElemRestriction
4924ce2993fSjeremylt   @param[out] elemsize    Variable to store size of elements
4934ce2993fSjeremylt 
4944ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
4954ce2993fSjeremylt 
49623617272Sjeremylt   @ref Advanced
4974ce2993fSjeremylt **/
4984ce2993fSjeremylt int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
4994ce2993fSjeremylt                                       CeedInt *elemsize) {
5004ce2993fSjeremylt   *elemsize = rstr->elemsize;
5014ce2993fSjeremylt   return 0;
5024ce2993fSjeremylt }
5034ce2993fSjeremylt 
5044ce2993fSjeremylt /**
5054ce2993fSjeremylt   @brief Get the number of degrees of freedom in the range of a
5064ce2993fSjeremylt          CeedElemRestriction
5074ce2993fSjeremylt 
5084ce2993fSjeremylt   @param rstr             CeedElemRestriction
5098795c945Sjeremylt   @param[out] numnodes    Variable to store number of nodes
5104ce2993fSjeremylt 
5114ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5124ce2993fSjeremylt 
51323617272Sjeremylt   @ref Advanced
5144ce2993fSjeremylt **/
5158795c945Sjeremylt int CeedElemRestrictionGetNumNodes(CeedElemRestriction rstr,
5168795c945Sjeremylt                                    CeedInt *numnodes) {
5178795c945Sjeremylt   *numnodes = rstr->nnodes;
5184ce2993fSjeremylt   return 0;
5194ce2993fSjeremylt }
5204ce2993fSjeremylt 
5214ce2993fSjeremylt /**
5224ce2993fSjeremylt   @brief Get the number of components in the elements of a
5234ce2993fSjeremylt          CeedElemRestriction
5244ce2993fSjeremylt 
5254ce2993fSjeremylt   @param rstr             CeedElemRestriction
5264ce2993fSjeremylt   @param[out] numcomp     Variable to store number of components
5274ce2993fSjeremylt 
5284ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5294ce2993fSjeremylt 
53023617272Sjeremylt   @ref Advanced
5314ce2993fSjeremylt **/
5324ce2993fSjeremylt int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
5334ce2993fSjeremylt                                         CeedInt *numcomp) {
5344ce2993fSjeremylt   *numcomp = rstr->ncomp;
5354ce2993fSjeremylt   return 0;
5364ce2993fSjeremylt }
5374ce2993fSjeremylt 
5384ce2993fSjeremylt /**
5394ce2993fSjeremylt   @brief Get the number of blocks in a CeedElemRestriction
5404ce2993fSjeremylt 
5414ce2993fSjeremylt   @param rstr             CeedElemRestriction
5424ce2993fSjeremylt   @param[out] numblock    Variable to store number of blocks
5434ce2993fSjeremylt 
5444ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5454ce2993fSjeremylt 
54623617272Sjeremylt   @ref Advanced
5474ce2993fSjeremylt **/
5484ce2993fSjeremylt int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
5494ce2993fSjeremylt                                     CeedInt *numblock) {
5504ce2993fSjeremylt   *numblock = rstr->nblk;
5514ce2993fSjeremylt   return 0;
5524ce2993fSjeremylt }
5534ce2993fSjeremylt 
5544ce2993fSjeremylt /**
5554ce2993fSjeremylt   @brief Get the size of blocks in the CeedElemRestriction
5564ce2993fSjeremylt 
557288c0443SJeremy L Thompson   @param rstr             CeedElemRestriction
5584ce2993fSjeremylt   @param[out] blksize     Variable to store size of blocks
5594ce2993fSjeremylt 
5604ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5614ce2993fSjeremylt 
56223617272Sjeremylt   @ref Advanced
5634ce2993fSjeremylt **/
5644ce2993fSjeremylt int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
5654ce2993fSjeremylt                                     CeedInt *blksize) {
5664ce2993fSjeremylt   *blksize = rstr->blksize;
5674ce2993fSjeremylt   return 0;
5684ce2993fSjeremylt }
5694ce2993fSjeremylt 
5704ce2993fSjeremylt /**
5714ce2993fSjeremylt   @brief Get the backend data of a CeedElemRestriction
5724ce2993fSjeremylt 
573288c0443SJeremy L Thompson   @param rstr             CeedElemRestriction
5744ce2993fSjeremylt   @param[out] data        Variable to store data
5754ce2993fSjeremylt 
5764ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5774ce2993fSjeremylt 
57823617272Sjeremylt   @ref Advanced
5794ce2993fSjeremylt **/
5801d102b48SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void **data) {
5814ce2993fSjeremylt   *data = rstr->data;
582d7b241e6Sjeremylt   return 0;
583d7b241e6Sjeremylt }
584d7b241e6Sjeremylt 
585d7b241e6Sjeremylt /**
586fe2413ffSjeremylt   @brief Set the backend data of a CeedElemRestriction
587fe2413ffSjeremylt 
588288c0443SJeremy L Thompson   @param[out] rstr        CeedElemRestriction
589fe2413ffSjeremylt   @param data             Data to set
590fe2413ffSjeremylt 
591fe2413ffSjeremylt   @return An error code: 0 - success, otherwise - failure
592fe2413ffSjeremylt 
593fe2413ffSjeremylt   @ref Advanced
594fe2413ffSjeremylt **/
5951d102b48SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void **data) {
596fe2413ffSjeremylt   rstr->data = *data;
597fe2413ffSjeremylt   return 0;
598fe2413ffSjeremylt }
599fe2413ffSjeremylt 
600fe2413ffSjeremylt /**
601f02ca4a2SJed Brown   @brief View a CeedElemRestriction
602f02ca4a2SJed Brown 
603f02ca4a2SJed Brown   @param[in] rstr    CeedElemRestriction to view
604f02ca4a2SJed Brown   @param[in] stream  Stream to write; typically stdout/stderr or a file
605f02ca4a2SJed Brown 
606f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
607f02ca4a2SJed Brown 
608f02ca4a2SJed Brown   @ref Utility
609f02ca4a2SJed Brown **/
610f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
6111d102b48SJeremy L Thompson   fprintf(stream, "CeedElemRestriction from (%d, %d) to %d elements with %d "
61261dbc9d2Sjeremylt           "nodes each and L-vector components %s\n", rstr->nnodes, rstr->ncomp,
61361dbc9d2Sjeremylt           rstr->nelem, rstr->elemsize, CeedInterlaceModes[rstr->imode]);
614f02ca4a2SJed Brown   return 0;
615f02ca4a2SJed Brown }
616f02ca4a2SJed Brown 
617f02ca4a2SJed Brown /**
618b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
619b11c1e72Sjeremylt 
6204ce2993fSjeremylt   @param rstr  CeedElemRestriction to destroy
621b11c1e72Sjeremylt 
622b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
623dfdf5a53Sjeremylt 
624dfdf5a53Sjeremylt   @ref Basic
625b11c1e72Sjeremylt **/
6264ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
627d7b241e6Sjeremylt   int ierr;
628d7b241e6Sjeremylt 
6291d102b48SJeremy L Thompson   if (!*rstr || --(*rstr)->refcount > 0)
6301d102b48SJeremy L Thompson     return 0;
6314ce2993fSjeremylt   if ((*rstr)->Destroy) {
6324ce2993fSjeremylt     ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr);
633d7b241e6Sjeremylt   }
6344ce2993fSjeremylt   ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr);
6354ce2993fSjeremylt   ierr = CeedFree(rstr); CeedChk(ierr);
636d7b241e6Sjeremylt   return 0;
637d7b241e6Sjeremylt }
638d7b241e6Sjeremylt 
639d7b241e6Sjeremylt /// @}
640