xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-elemrestriction.c (revision 074cb4162e0215e222ad42d17a0b66a502b190eb)
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
30a8d32208Sjeremylt   @param lmode      Ordering of the ncomp components, i.e. it specifies
31a8d32208Sjeremylt                       the ordering of the components of the L-vector used
32a8d32208Sjeremylt                       by this CeedElemRestriction. CEED_NOTRANSPOSE indicates
33a8d32208Sjeremylt                       the component is the outermost index and CEED_TRANSPOSE
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 **/
59a8d32208Sjeremylt int CeedElemRestrictionCreate(Ceed ceed,  CeedTransposeMode lmode,
60a8d32208Sjeremylt                               CeedInt nelem, CeedInt elemsize, CeedInt nnodes,
61a8d32208Sjeremylt                               CeedInt ncomp, CeedMemType mtype,
62d7b241e6Sjeremylt                               CeedCopyMode cmode, const CeedInt *indices,
634ce2993fSjeremylt                               CeedElemRestriction *rstr) {
64d7b241e6Sjeremylt   int ierr;
65d7b241e6Sjeremylt 
665fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
675fe0d4faSjeremylt     Ceed delegate;
68aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
69aefd8378Sjeremylt     CeedChk(ierr);
705fe0d4faSjeremylt 
715fe0d4faSjeremylt     if (!delegate)
72c042f62fSJeremy L Thompson       // LCOV_EXCL_START
73d7b241e6Sjeremylt       return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
74c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
755fe0d4faSjeremylt 
76a8d32208Sjeremylt     ierr = CeedElemRestrictionCreate(delegate, lmode, nelem, elemsize,
778795c945Sjeremylt                                      nnodes, ncomp, mtype, cmode,
784ce2993fSjeremylt                                      indices, rstr); CeedChk(ierr);
795fe0d4faSjeremylt     return 0;
805fe0d4faSjeremylt   }
815fe0d4faSjeremylt 
824ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
834ce2993fSjeremylt   (*rstr)->ceed = ceed;
84d7b241e6Sjeremylt   ceed->refcount++;
854ce2993fSjeremylt   (*rstr)->refcount = 1;
86a8d32208Sjeremylt   (*rstr)->lmode = lmode;
874ce2993fSjeremylt   (*rstr)->nelem = nelem;
884ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
898795c945Sjeremylt   (*rstr)->nnodes = nnodes;
904ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
914ce2993fSjeremylt   (*rstr)->nblk = nelem;
924ce2993fSjeremylt   (*rstr)->blksize = 1;
934ce2993fSjeremylt   ierr = ceed->ElemRestrictionCreate(mtype, cmode, indices, *rstr); CeedChk(ierr);
94d7b241e6Sjeremylt   return 0;
95d7b241e6Sjeremylt }
96d7b241e6Sjeremylt 
97d7b241e6Sjeremylt /**
98b11c1e72Sjeremylt   @brief Create an identity CeedElemRestriction
99d7b241e6Sjeremylt 
100b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
101a8d32208Sjeremylt   @param lmode      Ordering of the ncomp components, i.e. it specifies
102a8d32208Sjeremylt                       the ordering of the components of the L-vector used
103a8d32208Sjeremylt                       by this CeedElemRestriction. CEED_NOTRANSPOSE indicates
104a8d32208Sjeremylt                       the component is the outermost index and CEED_TRANSPOSE
105a8d32208Sjeremylt                       indicates the component is the innermost index in
106a8d32208Sjeremylt                       ordering of the L-vector.
107b11c1e72Sjeremylt   @param nelem      Number of elements described in the @a indices array
108b11c1e72Sjeremylt   @param elemsize   Size (number of "nodes") per element
1098795c945Sjeremylt   @param nnodes     The number of nodes in the L-vector. The input CeedVector
1108795c945Sjeremylt                       to which the restriction will be applied is of size
1118795c945Sjeremylt                       @a nnodes * @a ncomp. This size may include data
112d7b241e6Sjeremylt                       used by other CeedElemRestriction objects describing
1138795c945Sjeremylt                       different types of elements.
114b11c1e72Sjeremylt   @param ncomp      Number of field components per interpolation node
11595bb1877Svaleriabarra                       (1 for scalar fields)
1164ce2993fSjeremylt   @param rstr       Address of the variable where the newly created
117b11c1e72Sjeremylt                       CeedElemRestriction will be stored
118d7b241e6Sjeremylt 
119b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
120dfdf5a53Sjeremylt 
121dfdf5a53Sjeremylt   @ref Basic
122b11c1e72Sjeremylt **/
123a8d32208Sjeremylt int CeedElemRestrictionCreateIdentity(Ceed ceed,  CeedTransposeMode lmode,
124a8d32208Sjeremylt                                       CeedInt nelem, CeedInt elemsize,
125a8d32208Sjeremylt                                       CeedInt nnodes, CeedInt ncomp,
126f90c8643Sjeremylt                                       CeedElemRestriction *rstr) {
127d7b241e6Sjeremylt   int ierr;
128d7b241e6Sjeremylt 
1295fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
1305fe0d4faSjeremylt     Ceed delegate;
131aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
132aefd8378Sjeremylt     CeedChk(ierr);
1335fe0d4faSjeremylt 
1345fe0d4faSjeremylt     if (!delegate)
135c042f62fSJeremy L Thompson       // LCOV_EXCL_START
1361d102b48SJeremy L Thompson       return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
137c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
1385fe0d4faSjeremylt 
139a8d32208Sjeremylt     ierr = CeedElemRestrictionCreateIdentity(delegate, lmode, nelem, elemsize,
1408795c945Sjeremylt            nnodes, ncomp, rstr); CeedChk(ierr);
1415fe0d4faSjeremylt     return 0;
1425fe0d4faSjeremylt   }
1435fe0d4faSjeremylt 
1444ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
1454ce2993fSjeremylt   (*rstr)->ceed = ceed;
146d7b241e6Sjeremylt   ceed->refcount++;
1474ce2993fSjeremylt   (*rstr)->refcount = 1;
148a8d32208Sjeremylt   (*rstr)->lmode = lmode;
1494ce2993fSjeremylt   (*rstr)->nelem = nelem;
1504ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
1518795c945Sjeremylt   (*rstr)->nnodes = nnodes;
1524ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
1534ce2993fSjeremylt   (*rstr)->nblk = nelem;
1544ce2993fSjeremylt   (*rstr)->blksize = 1;
1551dfeef1dSjeremylt   ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL,
1561dfeef1dSjeremylt                                      *rstr);
1574b8bea3bSJed Brown   CeedChk(ierr);
158d7b241e6Sjeremylt   return 0;
159d7b241e6Sjeremylt }
160d7b241e6Sjeremylt 
161d7b241e6Sjeremylt /**
162b11c1e72Sjeremylt   @brief Permute and pad indices for a blocked restriction
163d7b241e6Sjeremylt 
1648795c945Sjeremylt   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
1658795c945Sjeremylt                       ordered list of the indices (into the input CeedVector)
1668795c945Sjeremylt                       for the unknowns corresponding to element i, where
16734138859Sjeremylt                       0 <= i < @a nelem. All indices must be in the range
1688795c945Sjeremylt                       [0, @a nnodes).
169ecf6354eSJed Brown   @param blkindices Array of permuted and padded indices of
170ecf6354eSJed Brown                       shape [@a nblk, @a elemsize, @a blksize].
171d7b241e6Sjeremylt   @param nblk       Number of blocks
172d7b241e6Sjeremylt   @param nelem      Number of elements
173d7b241e6Sjeremylt   @param blksize    Number of elements in a block
174d7b241e6Sjeremylt   @param elemsize   Size of each element
175d7b241e6Sjeremylt 
176b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
177b11c1e72Sjeremylt 
178dfdf5a53Sjeremylt   @ref Utility
179b11c1e72Sjeremylt **/
180dfdf5a53Sjeremylt int CeedPermutePadIndices(const CeedInt *indices, CeedInt *blkindices,
181692c2638Sjeremylt                           CeedInt nblk, CeedInt nelem, CeedInt blksize,
182692c2638Sjeremylt                           CeedInt elemsize) {
183d7b241e6Sjeremylt   for (CeedInt e = 0; e < nblk*blksize; e+=blksize)
184d7b241e6Sjeremylt     for (int j = 0; j < blksize; j++)
185d7b241e6Sjeremylt       for (int k = 0; k < elemsize; k++)
186d7b241e6Sjeremylt         blkindices[e*elemsize + k*blksize + j]
187d7b241e6Sjeremylt           = indices[CeedIntMin(e+j,nelem-1)*elemsize + k];
188dfdf5a53Sjeremylt   return 0;
189d7b241e6Sjeremylt }
190d7b241e6Sjeremylt 
191d7b241e6Sjeremylt /**
192b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
193d7b241e6Sjeremylt 
194d7b241e6Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created.
195a8d32208Sjeremylt   @param lmode      Ordering of the ncomp components, i.e. it specifies
196a8d32208Sjeremylt                       the ordering of the components of the L-vector used
197a8d32208Sjeremylt                       by this CeedElemRestriction. CEED_NOTRANSPOSE indicates
198a8d32208Sjeremylt                       the component is the outermost index and CEED_TRANSPOSE
199a8d32208Sjeremylt                       indicates the component is the innermost index in
200a8d32208Sjeremylt                       ordering of the L-vector.
201d7b241e6Sjeremylt   @param nelem      Number of elements described in the @a indices array.
202b11c1e72Sjeremylt   @param elemsize   Size (number of unknowns) per element
203b11c1e72Sjeremylt   @param blksize    Number of elements in a block
2048795c945Sjeremylt   @param nnodes     The number of nodes in the L-vector. The input CeedVector
2058795c945Sjeremylt                       to which the restriction will be applied is of size
2068795c945Sjeremylt                       @a nnodes * @a ncomp. This size may include data
207d7b241e6Sjeremylt                       used by other CeedElemRestriction objects describing
208d7b241e6Sjeremylt                       different types of elements.
20995bb1877Svaleriabarra   @param ncomp      Number of field components per interpolation node
21095bb1877Svaleriabarra                       (1 for scalar fields)
211b11c1e72Sjeremylt   @param mtype      Memory type of the @a indices array, see CeedMemType
212b11c1e72Sjeremylt   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
2138795c945Sjeremylt   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
2148795c945Sjeremylt                       ordered list of the indices (into the input CeedVector)
2158795c945Sjeremylt                       for the unknowns corresponding to element i, where
21634138859Sjeremylt                       0 <= i < @a nelem. All indices must be in the range
2178795c945Sjeremylt                       [0, @a nnodes). The backend will permute and pad this
2188795c945Sjeremylt                       array to the desired ordering for the blocksize, which is
2198795c945Sjeremylt                       typically given by the backend. The default reordering is
2208795c945Sjeremylt                       to interlace elements.
2214ce2993fSjeremylt   @param rstr       Address of the variable where the newly created
222b11c1e72Sjeremylt                       CeedElemRestriction will be stored
223d7b241e6Sjeremylt 
224b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
225dfdf5a53Sjeremylt 
226dfdf5a53Sjeremylt   @ref Advanced
227b11c1e72Sjeremylt  **/
228a8d32208Sjeremylt int CeedElemRestrictionCreateBlocked(Ceed ceed,  CeedTransposeMode lmode,
229a8d32208Sjeremylt                                      CeedInt nelem, CeedInt elemsize,
2308795c945Sjeremylt                                      CeedInt blksize, CeedInt nnodes,
2318795c945Sjeremylt                                      CeedInt ncomp, CeedMemType mtype,
2328795c945Sjeremylt                                      CeedCopyMode cmode, const CeedInt *indices,
2334ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
234d7b241e6Sjeremylt   int ierr;
235d7b241e6Sjeremylt   CeedInt *blkindices;
236d7b241e6Sjeremylt   CeedInt nblk = (nelem / blksize) + !!(nelem % blksize);
237d7b241e6Sjeremylt 
2385fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
2395fe0d4faSjeremylt     Ceed delegate;
240aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
241aefd8378Sjeremylt     CeedChk(ierr);
2425fe0d4faSjeremylt 
2435fe0d4faSjeremylt     if (!delegate)
244c042f62fSJeremy L Thompson       // LCOV_EXCL_START
2451d102b48SJeremy L Thompson       return CeedError(ceed, 1, "Backend does not support "
2461d102b48SJeremy L Thompson                        "ElemRestrictionCreateBlocked");
247c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
2485fe0d4faSjeremylt 
249a8d32208Sjeremylt     ierr = CeedElemRestrictionCreateBlocked(delegate, lmode, nelem, elemsize,
2508795c945Sjeremylt                                             blksize, nnodes, ncomp, mtype, cmode,
2514ce2993fSjeremylt                                             indices, rstr); CeedChk(ierr);
2525fe0d4faSjeremylt     return 0;
2535fe0d4faSjeremylt   }
254d7b241e6Sjeremylt 
2554ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
256d7b241e6Sjeremylt 
257d7b241e6Sjeremylt   if (indices) {
258de686571SJeremy L Thompson     ierr = CeedCalloc(nblk*blksize*elemsize, &blkindices); CeedChk(ierr);
2594b8bea3bSJed Brown     ierr = CeedPermutePadIndices(indices, blkindices, nblk, nelem, blksize,
2604b8bea3bSJed Brown                                  elemsize);
261dfdf5a53Sjeremylt     CeedChk(ierr);
262d7b241e6Sjeremylt   } else {
263d7b241e6Sjeremylt     blkindices = NULL;
264d7b241e6Sjeremylt   }
265d7b241e6Sjeremylt 
2664ce2993fSjeremylt   (*rstr)->ceed = ceed;
267d7b241e6Sjeremylt   ceed->refcount++;
2684ce2993fSjeremylt   (*rstr)->refcount = 1;
269a8d32208Sjeremylt   (*rstr)->lmode = lmode;
2704ce2993fSjeremylt   (*rstr)->nelem = nelem;
2714ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
2728795c945Sjeremylt   (*rstr)->nnodes = nnodes;
2734ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
2744ce2993fSjeremylt   (*rstr)->nblk = nblk;
2754ce2993fSjeremylt   (*rstr)->blksize = blksize;
276667bc5fcSjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
2777f823360Sjeremylt          (const CeedInt *) blkindices, *rstr); CeedChk(ierr);
278d7b241e6Sjeremylt 
2791d102b48SJeremy L Thompson   if (cmode == CEED_OWN_POINTER) {
280d7b241e6Sjeremylt     ierr = CeedFree(&indices); CeedChk(ierr);
2811d102b48SJeremy L Thompson   }
282d7b241e6Sjeremylt 
283d7b241e6Sjeremylt   return 0;
284d7b241e6Sjeremylt }
285d7b241e6Sjeremylt 
286b11c1e72Sjeremylt /**
287b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
288b11c1e72Sjeremylt 
2894ce2993fSjeremylt   @param rstr  CeedElemRestriction
290b11c1e72Sjeremylt   @param lvec  The address of the L-vector to be created, or NULL
291b11c1e72Sjeremylt   @param evec  The address of the E-vector to be created, or NULL
292b11c1e72Sjeremylt 
293b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
294dfdf5a53Sjeremylt 
295dfdf5a53Sjeremylt   @ref Advanced
296b11c1e72Sjeremylt **/
2974ce2993fSjeremylt int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *lvec,
298d7b241e6Sjeremylt                                     CeedVector *evec) {
299d7b241e6Sjeremylt   int ierr;
300d7b241e6Sjeremylt   CeedInt n, m;
3018795c945Sjeremylt   m = rstr->nnodes * rstr->ncomp;
3024ce2993fSjeremylt   n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
303d7b241e6Sjeremylt   if (lvec) {
3044ce2993fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, m, lvec); CeedChk(ierr);
305d7b241e6Sjeremylt   }
306d7b241e6Sjeremylt   if (evec) {
3074ce2993fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, n, evec); CeedChk(ierr);
308d7b241e6Sjeremylt   }
309d7b241e6Sjeremylt   return 0;
310d7b241e6Sjeremylt }
311d7b241e6Sjeremylt 
312d7b241e6Sjeremylt /**
313d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
314d7b241e6Sjeremylt 
3154ce2993fSjeremylt   @param rstr    CeedElemRestriction
316d7b241e6Sjeremylt   @param tmode   Apply restriction or transpose
3177aaeacdcSjeremylt   @param u       Input vector (of shape [@a nnodes, @a ncomp] when
3187aaeacdcSjeremylt                    tmode=CEED_NOTRANSPOSE, lmode=CEED_TRANSPOSE)
319a8d32208Sjeremylt   @param ru      Output vector (of shape [@a nelem * @a elemsize] when
3207aaeacdcSjeremylt                    tmode=CEED_NOTRANSPOSE). Ordering of the e-vector is decided
3217aaeacdcSjeremylt                    by the backend.
322d7b241e6Sjeremylt   @param request Request or CEED_REQUEST_IMMEDIATE
323b11c1e72Sjeremylt 
324b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
325dfdf5a53Sjeremylt 
326dfdf5a53Sjeremylt   @ref Advanced
327b11c1e72Sjeremylt **/
3284ce2993fSjeremylt int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode tmode,
329a8d32208Sjeremylt                              CeedVector u, CeedVector ru,
330a8d32208Sjeremylt                              CeedRequest *request) {
331d7b241e6Sjeremylt   CeedInt m,n;
332d7b241e6Sjeremylt   int ierr;
333d7b241e6Sjeremylt 
334d7b241e6Sjeremylt   if (tmode == CEED_NOTRANSPOSE) {
3354ce2993fSjeremylt     m = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
3368795c945Sjeremylt     n = rstr->nnodes * rstr->ncomp;
337d7b241e6Sjeremylt   } else {
3388795c945Sjeremylt     m = rstr->nnodes * rstr->ncomp;
3394ce2993fSjeremylt     n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
340d7b241e6Sjeremylt   }
341d7b241e6Sjeremylt   if (n != u->length)
342c042f62fSJeremy L Thompson     // LCOV_EXCL_START
3431d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Input vector size %d not compatible with "
3441d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
345c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
346a8d32208Sjeremylt   if (m != ru->length)
347c042f62fSJeremy L Thompson     // LCOV_EXCL_START
3481d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Output vector size %d not compatible with "
349a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
350c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
351*074cb416Sjeremylt   ierr = rstr->Apply(rstr, tmode, u, ru, request); CeedChk(ierr);
352d7b241e6Sjeremylt 
353d7b241e6Sjeremylt   return 0;
354d7b241e6Sjeremylt }
355d7b241e6Sjeremylt 
356d7b241e6Sjeremylt /**
357d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
358be9261b7Sjeremylt 
359be9261b7Sjeremylt   @param rstr    CeedElemRestriction
3601f37b403Sjeremylt   @param block   Block number to restrict to/from, i.e. block=0 will handle
3611f37b403Sjeremylt                    elements [0 : blksize] and block=3 will handle elements
3621f37b403Sjeremylt                    [3*blksize : 4*blksize]
363be9261b7Sjeremylt   @param tmode   Apply restriction or transpose
3647aaeacdcSjeremylt   @param u       Input vector (of shape [@a nnodes, @a ncomp] when
3657aaeacdcSjeremylt                    tmode=CEED_NOTRANSPOSE, lmode=CEED_TRANSPOSE)
366a8d32208Sjeremylt   @param ru      Output vector (of shape [@a blksize * @a elemsize] when
3677aaeacdcSjeremylt                    tmode=CEED_NOTRANSPOSE). Ordering of the e-vector is decided
3687aaeacdcSjeremylt                    by the backend.
369be9261b7Sjeremylt   @param request Request or CEED_REQUEST_IMMEDIATE
370be9261b7Sjeremylt 
371be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
372be9261b7Sjeremylt 
373be9261b7Sjeremylt   @ref Advanced
374be9261b7Sjeremylt **/
375be9261b7Sjeremylt int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block,
376a8d32208Sjeremylt                                   CeedTransposeMode tmode, CeedVector u,
377a8d32208Sjeremylt                                   CeedVector ru, CeedRequest *request) {
378be9261b7Sjeremylt   CeedInt m,n;
379be9261b7Sjeremylt   int ierr;
380be9261b7Sjeremylt 
381be9261b7Sjeremylt   if (tmode == CEED_NOTRANSPOSE) {
382be9261b7Sjeremylt     m = rstr->blksize * rstr->elemsize * rstr->ncomp;
3838795c945Sjeremylt     n = rstr->nnodes * rstr->ncomp;
384be9261b7Sjeremylt   } else {
3858795c945Sjeremylt     m = rstr->nnodes * rstr->ncomp;
386be9261b7Sjeremylt     n = rstr->blksize * rstr->elemsize * rstr->ncomp;
387be9261b7Sjeremylt   }
388be9261b7Sjeremylt   if (n != u->length)
389c042f62fSJeremy L Thompson     // LCOV_EXCL_START
3901d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Input vector size %d not compatible with "
3911d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
392c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
393a8d32208Sjeremylt   if (m != ru->length)
394c042f62fSJeremy L Thompson     // LCOV_EXCL_START
3951d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Output vector size %d not compatible with "
396a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
397c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
398be9261b7Sjeremylt   if (rstr->blksize*block > rstr->nelem)
399c042f62fSJeremy L Thompson     // LCOV_EXCL_START
4001d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Cannot retrieve block %d, element %d > "
4011d102b48SJeremy L Thompson                      "total elements %d", block, rstr->blksize*block,
4021d102b48SJeremy L Thompson                      rstr->nelem);
403c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
404*074cb416Sjeremylt   ierr = rstr->ApplyBlock(rstr, block, tmode, u, ru, request);
405be9261b7Sjeremylt   CeedChk(ierr);
406be9261b7Sjeremylt 
407be9261b7Sjeremylt   return 0;
408be9261b7Sjeremylt }
409be9261b7Sjeremylt 
410be9261b7Sjeremylt /**
411d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
4121469ee4dSjeremylt 
4131469ee4dSjeremylt   @param rstr             CeedElemRestriction
414d9e1f99aSValeria Barra   @param[out] mult        Vector to store multiplicity (of size nnodes)
4151469ee4dSjeremylt 
4161469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
4171469ee4dSjeremylt 
4181469ee4dSjeremylt   @ref Advanced
4191469ee4dSjeremylt **/
4201469ee4dSjeremylt int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr,
4211469ee4dSjeremylt                                        CeedVector mult) {
4221469ee4dSjeremylt   int ierr;
4231469ee4dSjeremylt   CeedVector evec;
4241469ee4dSjeremylt 
4251469ee4dSjeremylt   // Create and set evec
4261469ee4dSjeremylt   ierr = CeedElemRestrictionCreateVector(rstr, NULL, &evec); CeedChk(ierr);
4271469ee4dSjeremylt   ierr = CeedVectorSetValue(evec, 1.0); CeedChk(ierr);
4281469ee4dSjeremylt 
4291469ee4dSjeremylt   // Apply to get multiplicity
430a8d32208Sjeremylt   ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, evec, mult,
431efc78312Sjeremylt                                   CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
4321469ee4dSjeremylt 
4331469ee4dSjeremylt   // Cleanup
4341469ee4dSjeremylt   ierr = CeedVectorDestroy(&evec); CeedChk(ierr);
4351469ee4dSjeremylt 
4361469ee4dSjeremylt   return 0;
4371469ee4dSjeremylt }
4381469ee4dSjeremylt 
4391469ee4dSjeremylt /**
4404ce2993fSjeremylt   @brief Get the Ceed associated with a CeedElemRestriction
4414ce2993fSjeremylt 
4424ce2993fSjeremylt   @param rstr             CeedElemRestriction
4434ce2993fSjeremylt   @param[out] ceed        Variable to store Ceed
4444ce2993fSjeremylt 
4454ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
4464ce2993fSjeremylt 
44723617272Sjeremylt   @ref Advanced
4484ce2993fSjeremylt **/
4494ce2993fSjeremylt int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
4504ce2993fSjeremylt   *ceed = rstr->ceed;
4514ce2993fSjeremylt   return 0;
4524ce2993fSjeremylt }
4534ce2993fSjeremylt 
4544ce2993fSjeremylt /**
455a8d32208Sjeremylt   @brief Get the L-vector layout mode of a CeedElemRestriction
456a8d32208Sjeremylt 
457a8d32208Sjeremylt   @param rstr             CeedElemRestriction
458a8d32208Sjeremylt   @param[out] lmode       Variable to store lmode
459a8d32208Sjeremylt 
460a8d32208Sjeremylt   @return An error code: 0 - success, otherwise - failure
461a8d32208Sjeremylt 
462a8d32208Sjeremylt   @ref Advanced
463a8d32208Sjeremylt **/
464a8d32208Sjeremylt int CeedElemRestrictionGetLMode(CeedElemRestriction rstr,
465a8d32208Sjeremylt                                 CeedTransposeMode *lmode) {
466a8d32208Sjeremylt   *lmode = rstr->lmode;
467a8d32208Sjeremylt   return 0;
468a8d32208Sjeremylt }
469a8d32208Sjeremylt 
470a8d32208Sjeremylt /**
471b11c1e72Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
472d7b241e6Sjeremylt 
4734ce2993fSjeremylt   @param rstr             CeedElemRestriction
474288c0443SJeremy L Thompson   @param[out] numelem     Variable to store number of elements
475b11c1e72Sjeremylt 
476b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
477dfdf5a53Sjeremylt 
47823617272Sjeremylt   @ref Advanced
479b11c1e72Sjeremylt **/
4804ce2993fSjeremylt int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
4814ce2993fSjeremylt                                       CeedInt *numelem) {
4824ce2993fSjeremylt   *numelem = rstr->nelem;
4834ce2993fSjeremylt   return 0;
4844ce2993fSjeremylt }
4854ce2993fSjeremylt 
4864ce2993fSjeremylt /**
4874ce2993fSjeremylt   @brief Get the size of elements in the CeedElemRestriction
4884ce2993fSjeremylt 
4894ce2993fSjeremylt   @param rstr             CeedElemRestriction
4904ce2993fSjeremylt   @param[out] elemsize    Variable to store size of elements
4914ce2993fSjeremylt 
4924ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
4934ce2993fSjeremylt 
49423617272Sjeremylt   @ref Advanced
4954ce2993fSjeremylt **/
4964ce2993fSjeremylt int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
4974ce2993fSjeremylt                                       CeedInt *elemsize) {
4984ce2993fSjeremylt   *elemsize = rstr->elemsize;
4994ce2993fSjeremylt   return 0;
5004ce2993fSjeremylt }
5014ce2993fSjeremylt 
5024ce2993fSjeremylt /**
5034ce2993fSjeremylt   @brief Get the number of degrees of freedom in the range of a
5044ce2993fSjeremylt          CeedElemRestriction
5054ce2993fSjeremylt 
5064ce2993fSjeremylt   @param rstr             CeedElemRestriction
5078795c945Sjeremylt   @param[out] numnodes    Variable to store number of nodes
5084ce2993fSjeremylt 
5094ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5104ce2993fSjeremylt 
51123617272Sjeremylt   @ref Advanced
5124ce2993fSjeremylt **/
5138795c945Sjeremylt int CeedElemRestrictionGetNumNodes(CeedElemRestriction rstr,
5148795c945Sjeremylt                                    CeedInt *numnodes) {
5158795c945Sjeremylt   *numnodes = rstr->nnodes;
5164ce2993fSjeremylt   return 0;
5174ce2993fSjeremylt }
5184ce2993fSjeremylt 
5194ce2993fSjeremylt /**
5204ce2993fSjeremylt   @brief Get the number of components in the elements of a
5214ce2993fSjeremylt          CeedElemRestriction
5224ce2993fSjeremylt 
5234ce2993fSjeremylt   @param rstr             CeedElemRestriction
5244ce2993fSjeremylt   @param[out] numcomp     Variable to store number of components
5254ce2993fSjeremylt 
5264ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5274ce2993fSjeremylt 
52823617272Sjeremylt   @ref Advanced
5294ce2993fSjeremylt **/
5304ce2993fSjeremylt int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
5314ce2993fSjeremylt                                         CeedInt *numcomp) {
5324ce2993fSjeremylt   *numcomp = rstr->ncomp;
5334ce2993fSjeremylt   return 0;
5344ce2993fSjeremylt }
5354ce2993fSjeremylt 
5364ce2993fSjeremylt /**
5374ce2993fSjeremylt   @brief Get the number of blocks in a CeedElemRestriction
5384ce2993fSjeremylt 
5394ce2993fSjeremylt   @param rstr             CeedElemRestriction
5404ce2993fSjeremylt   @param[out] numblock    Variable to store number of blocks
5414ce2993fSjeremylt 
5424ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5434ce2993fSjeremylt 
54423617272Sjeremylt   @ref Advanced
5454ce2993fSjeremylt **/
5464ce2993fSjeremylt int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
5474ce2993fSjeremylt                                     CeedInt *numblock) {
5484ce2993fSjeremylt   *numblock = rstr->nblk;
5494ce2993fSjeremylt   return 0;
5504ce2993fSjeremylt }
5514ce2993fSjeremylt 
5524ce2993fSjeremylt /**
5534ce2993fSjeremylt   @brief Get the size of blocks in the CeedElemRestriction
5544ce2993fSjeremylt 
555288c0443SJeremy L Thompson   @param rstr             CeedElemRestriction
5564ce2993fSjeremylt   @param[out] blksize     Variable to store size of blocks
5574ce2993fSjeremylt 
5584ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5594ce2993fSjeremylt 
56023617272Sjeremylt   @ref Advanced
5614ce2993fSjeremylt **/
5624ce2993fSjeremylt int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
5634ce2993fSjeremylt                                     CeedInt *blksize) {
5644ce2993fSjeremylt   *blksize = rstr->blksize;
5654ce2993fSjeremylt   return 0;
5664ce2993fSjeremylt }
5674ce2993fSjeremylt 
5684ce2993fSjeremylt /**
5694ce2993fSjeremylt   @brief Get the backend data of a CeedElemRestriction
5704ce2993fSjeremylt 
571288c0443SJeremy L Thompson   @param rstr             CeedElemRestriction
5724ce2993fSjeremylt   @param[out] data        Variable to store data
5734ce2993fSjeremylt 
5744ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5754ce2993fSjeremylt 
57623617272Sjeremylt   @ref Advanced
5774ce2993fSjeremylt **/
5781d102b48SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void **data) {
5794ce2993fSjeremylt   *data = rstr->data;
580d7b241e6Sjeremylt   return 0;
581d7b241e6Sjeremylt }
582d7b241e6Sjeremylt 
583d7b241e6Sjeremylt /**
584fe2413ffSjeremylt   @brief Set the backend data of a CeedElemRestriction
585fe2413ffSjeremylt 
586288c0443SJeremy L Thompson   @param[out] rstr        CeedElemRestriction
587fe2413ffSjeremylt   @param data             Data to set
588fe2413ffSjeremylt 
589fe2413ffSjeremylt   @return An error code: 0 - success, otherwise - failure
590fe2413ffSjeremylt 
591fe2413ffSjeremylt   @ref Advanced
592fe2413ffSjeremylt **/
5931d102b48SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void **data) {
594fe2413ffSjeremylt   rstr->data = *data;
595fe2413ffSjeremylt   return 0;
596fe2413ffSjeremylt }
597fe2413ffSjeremylt 
598fe2413ffSjeremylt /**
599f02ca4a2SJed Brown   @brief View a CeedElemRestriction
600f02ca4a2SJed Brown 
601f02ca4a2SJed Brown   @param[in] rstr    CeedElemRestriction to view
602f02ca4a2SJed Brown   @param[in] stream  Stream to write; typically stdout/stderr or a file
603f02ca4a2SJed Brown 
604f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
605f02ca4a2SJed Brown 
606f02ca4a2SJed Brown   @ref Utility
607f02ca4a2SJed Brown **/
608f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
6091d102b48SJeremy L Thompson   fprintf(stream, "CeedElemRestriction from (%d, %d) to %d elements with %d "
610a8d32208Sjeremylt           "nodes each and L-vector layout %s\n", rstr->nnodes, rstr->ncomp,
611a8d32208Sjeremylt           rstr->nelem, rstr->elemsize, rstr->lmode == CEED_NOTRANSPOSE ?
612a8d32208Sjeremylt           "CEED_NOTRANSPOSE" : "CEED_TRANSPOSE");
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