xref: /libCEED/interface/ceed-elemrestriction.c (revision c042f62f62e10e1321eb699b116e67a6568d5716)
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
30b11c1e72Sjeremylt   @param nelem      Number of elements described in the @a indices array
31b11c1e72Sjeremylt   @param elemsize   Size (number of "nodes") per element
328795c945Sjeremylt   @param nnodes     The number of nodes in the L-vector. The input CeedVector
338795c945Sjeremylt                       to which the restriction will be applied is of size
348795c945Sjeremylt                       @a nnodes * @a ncomp. This size may include data
35d7b241e6Sjeremylt                       used by other CeedElemRestriction objects describing
36d7b241e6Sjeremylt                       different types of elements.
37b11c1e72Sjeremylt   @param ncomp      Number of field components per interpolation node
38b11c1e72Sjeremylt   @param mtype      Memory type of the @a indices array, see CeedMemType
39b11c1e72Sjeremylt   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
408795c945Sjeremylt   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
418795c945Sjeremylt                       ordered list of the indices (into the input CeedVector)
428795c945Sjeremylt                       for the unknowns corresponding to element i, where
438795c945Sjeremylt                       0 <= i < @a nelements. All indices must be in the range
448795c945Sjeremylt                       [0, @a nnodes].
454ce2993fSjeremylt   @param[out] rstr  Address of the variable where the newly created
46b11c1e72Sjeremylt                       CeedElemRestriction will be stored
47d7b241e6Sjeremylt 
48b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
49dfdf5a53Sjeremylt 
50dfdf5a53Sjeremylt   @ref Basic
51b11c1e72Sjeremylt **/
52d7b241e6Sjeremylt int CeedElemRestrictionCreate(Ceed ceed, CeedInt nelem, CeedInt elemsize,
538795c945Sjeremylt                               CeedInt nnodes, CeedInt ncomp, CeedMemType mtype,
54d7b241e6Sjeremylt                               CeedCopyMode cmode, const CeedInt *indices,
554ce2993fSjeremylt                               CeedElemRestriction *rstr) {
56d7b241e6Sjeremylt   int ierr;
57d7b241e6Sjeremylt 
585fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
595fe0d4faSjeremylt     Ceed delegate;
60aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
61aefd8378Sjeremylt     CeedChk(ierr);
625fe0d4faSjeremylt 
635fe0d4faSjeremylt     if (!delegate)
64*c042f62fSJeremy L Thompson       // LCOV_EXCL_START
65d7b241e6Sjeremylt       return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
66*c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
675fe0d4faSjeremylt 
685fe0d4faSjeremylt     ierr = CeedElemRestrictionCreate(delegate, nelem, elemsize,
698795c945Sjeremylt                                      nnodes, ncomp, mtype, cmode,
704ce2993fSjeremylt                                      indices, rstr); CeedChk(ierr);
715fe0d4faSjeremylt     return 0;
725fe0d4faSjeremylt   }
735fe0d4faSjeremylt 
744ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
754ce2993fSjeremylt   (*rstr)->ceed = ceed;
76d7b241e6Sjeremylt   ceed->refcount++;
774ce2993fSjeremylt   (*rstr)->refcount = 1;
784ce2993fSjeremylt   (*rstr)->nelem = nelem;
794ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
808795c945Sjeremylt   (*rstr)->nnodes = nnodes;
814ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
824ce2993fSjeremylt   (*rstr)->nblk = nelem;
834ce2993fSjeremylt   (*rstr)->blksize = 1;
844ce2993fSjeremylt   ierr = ceed->ElemRestrictionCreate(mtype, cmode, indices, *rstr); CeedChk(ierr);
85d7b241e6Sjeremylt   return 0;
86d7b241e6Sjeremylt }
87d7b241e6Sjeremylt 
88d7b241e6Sjeremylt /**
89b11c1e72Sjeremylt   @brief Create an identity CeedElemRestriction
90d7b241e6Sjeremylt 
91b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
92b11c1e72Sjeremylt   @param nelem      Number of elements described in the @a indices array
93b11c1e72Sjeremylt   @param elemsize   Size (number of "nodes") per element
948795c945Sjeremylt   @param nnodes     The number of nodes in the L-vector. The input CeedVector
958795c945Sjeremylt                       to which the restriction will be applied is of size
968795c945Sjeremylt                       @a nnodes * @a ncomp. This size may include data
97d7b241e6Sjeremylt                       used by other CeedElemRestriction objects describing
988795c945Sjeremylt                       different types of elements.
99b11c1e72Sjeremylt   @param ncomp      Number of field components per interpolation node
1004ce2993fSjeremylt   @param rstr       Address of the variable where the newly created
101b11c1e72Sjeremylt                       CeedElemRestriction will be stored
102d7b241e6Sjeremylt 
103b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
104dfdf5a53Sjeremylt 
105dfdf5a53Sjeremylt   @ref Basic
106b11c1e72Sjeremylt **/
1074b8bea3bSJed Brown int CeedElemRestrictionCreateIdentity(Ceed ceed, CeedInt nelem,
108f90c8643Sjeremylt                                       CeedInt elemsize, CeedInt nnodes,
109f90c8643Sjeremylt                                       CeedInt ncomp,
110f90c8643Sjeremylt                                       CeedElemRestriction *rstr) {
111d7b241e6Sjeremylt   int ierr;
112d7b241e6Sjeremylt 
1135fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
1145fe0d4faSjeremylt     Ceed delegate;
115aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
116aefd8378Sjeremylt     CeedChk(ierr);
1175fe0d4faSjeremylt 
1185fe0d4faSjeremylt     if (!delegate)
119*c042f62fSJeremy L Thompson       // LCOV_EXCL_START
1204b8bea3bSJed Brown       return CeedError(ceed, 1,
1215fe0d4faSjeremylt                        "Backend does not support ElemRestrictionCreate");
122*c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
1235fe0d4faSjeremylt 
1245fe0d4faSjeremylt     ierr = CeedElemRestrictionCreateIdentity(delegate, nelem, elemsize,
1258795c945Sjeremylt            nnodes, ncomp, rstr); CeedChk(ierr);
1265fe0d4faSjeremylt     return 0;
1275fe0d4faSjeremylt   }
1285fe0d4faSjeremylt 
1294ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
1304ce2993fSjeremylt   (*rstr)->ceed = ceed;
131d7b241e6Sjeremylt   ceed->refcount++;
1324ce2993fSjeremylt   (*rstr)->refcount = 1;
1334ce2993fSjeremylt   (*rstr)->nelem = nelem;
1344ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
1358795c945Sjeremylt   (*rstr)->nnodes = nnodes;
1364ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
1374ce2993fSjeremylt   (*rstr)->nblk = nelem;
1384ce2993fSjeremylt   (*rstr)->blksize = 1;
1391dfeef1dSjeremylt   ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL,
1401dfeef1dSjeremylt                                      *rstr);
1414b8bea3bSJed Brown   CeedChk(ierr);
142d7b241e6Sjeremylt   return 0;
143d7b241e6Sjeremylt }
144d7b241e6Sjeremylt 
145d7b241e6Sjeremylt /**
146b11c1e72Sjeremylt   @brief Permute and pad indices for a blocked restriction
147d7b241e6Sjeremylt 
1488795c945Sjeremylt   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
1498795c945Sjeremylt                       ordered list of the indices (into the input CeedVector)
1508795c945Sjeremylt                       for the unknowns corresponding to element i, where
1518795c945Sjeremylt                       0 <= i < @a nelements. All indices must be in the range
1528795c945Sjeremylt                       [0, @a nnodes).
153ecf6354eSJed Brown   @param blkindices Array of permuted and padded indices of
154ecf6354eSJed Brown                       shape [@a nblk, @a elemsize, @a blksize].
155d7b241e6Sjeremylt   @param nblk       Number of blocks
156d7b241e6Sjeremylt   @param nelem      Number of elements
157d7b241e6Sjeremylt   @param blksize    Number of elements in a block
158d7b241e6Sjeremylt   @param elemsize   Size of each element
159d7b241e6Sjeremylt 
160b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
161b11c1e72Sjeremylt 
162dfdf5a53Sjeremylt   @ref Utility
163b11c1e72Sjeremylt **/
164dfdf5a53Sjeremylt int CeedPermutePadIndices(const CeedInt *indices, CeedInt *blkindices,
165d7b241e6Sjeremylt                           CeedInt nblk, CeedInt nelem,
166d7b241e6Sjeremylt                           CeedInt blksize, CeedInt elemsize) {
167d7b241e6Sjeremylt   for (CeedInt e = 0; e < nblk*blksize; e+=blksize)
168d7b241e6Sjeremylt     for (int j = 0; j < blksize; j++)
169d7b241e6Sjeremylt       for (int k = 0; k < elemsize; k++)
170d7b241e6Sjeremylt         blkindices[e*elemsize + k*blksize + j]
171d7b241e6Sjeremylt           = indices[CeedIntMin(e+j,nelem-1)*elemsize + k];
172dfdf5a53Sjeremylt   return 0;
173d7b241e6Sjeremylt }
174d7b241e6Sjeremylt 
175d7b241e6Sjeremylt /**
176b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
177d7b241e6Sjeremylt 
178d7b241e6Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created.
179d7b241e6Sjeremylt   @param nelem      Number of elements described in the @a indices array.
180b11c1e72Sjeremylt   @param elemsize   Size (number of unknowns) per element
181b11c1e72Sjeremylt   @param blksize    Number of elements in a block
1828795c945Sjeremylt   @param nnodes     The number of nodes in the L-vector. The input CeedVector
1838795c945Sjeremylt                       to which the restriction will be applied is of size
1848795c945Sjeremylt                       @a nnodes * @a ncomp. This size may include data
185d7b241e6Sjeremylt                       used by other CeedElemRestriction objects describing
186d7b241e6Sjeremylt                       different types of elements.
187b11c1e72Sjeremylt   @param ncomp      Number of components stored at each node
188b11c1e72Sjeremylt   @param mtype      Memory type of the @a indices array, see CeedMemType
189b11c1e72Sjeremylt   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
1908795c945Sjeremylt   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
1918795c945Sjeremylt                       ordered list of the indices (into the input CeedVector)
1928795c945Sjeremylt                       for the unknowns corresponding to element i, where
1938795c945Sjeremylt                       0 <= i < @a nelements. All indices must be in the range
1948795c945Sjeremylt                       [0, @a nnodes). The backend will permute and pad this
1958795c945Sjeremylt                       array to the desired ordering for the blocksize, which is
1968795c945Sjeremylt                       typically given by the backend. The default reordering is
1978795c945Sjeremylt                       to interlace elements.
1984ce2993fSjeremylt   @param rstr       Address of the variable where the newly created
199b11c1e72Sjeremylt                       CeedElemRestriction will be stored
200d7b241e6Sjeremylt 
201b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
202dfdf5a53Sjeremylt 
203dfdf5a53Sjeremylt   @ref Advanced
204b11c1e72Sjeremylt  **/
205d7b241e6Sjeremylt int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt nelem, CeedInt elemsize,
2068795c945Sjeremylt                                      CeedInt blksize, CeedInt nnodes,
2078795c945Sjeremylt                                      CeedInt ncomp, CeedMemType mtype,
2088795c945Sjeremylt                                      CeedCopyMode cmode, const CeedInt *indices,
2094ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
210d7b241e6Sjeremylt   int ierr;
211d7b241e6Sjeremylt   CeedInt *blkindices;
212d7b241e6Sjeremylt   CeedInt nblk = (nelem / blksize) + !!(nelem % blksize);
213d7b241e6Sjeremylt 
2145fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
2155fe0d4faSjeremylt     Ceed delegate;
216aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
217aefd8378Sjeremylt     CeedChk(ierr);
2185fe0d4faSjeremylt 
2195fe0d4faSjeremylt     if (!delegate)
220*c042f62fSJeremy L Thompson       // LCOV_EXCL_START
221d7b241e6Sjeremylt       return CeedError(ceed, 1,
222d7b241e6Sjeremylt                        "Backend does not support ElemRestrictionCreateBlocked");
223*c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
2245fe0d4faSjeremylt 
2255fe0d4faSjeremylt     ierr = CeedElemRestrictionCreateBlocked(delegate, nelem, elemsize,
2268795c945Sjeremylt                                             blksize, nnodes, ncomp, mtype, cmode,
2274ce2993fSjeremylt                                             indices, rstr); CeedChk(ierr);
2285fe0d4faSjeremylt     return 0;
2295fe0d4faSjeremylt   }
230d7b241e6Sjeremylt 
2314ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
232d7b241e6Sjeremylt 
233d7b241e6Sjeremylt   if (indices) {
234de686571SJeremy L Thompson     ierr = CeedCalloc(nblk*blksize*elemsize, &blkindices); CeedChk(ierr);
2354b8bea3bSJed Brown     ierr = CeedPermutePadIndices(indices, blkindices, nblk, nelem, blksize,
2364b8bea3bSJed Brown                                  elemsize);
237dfdf5a53Sjeremylt     CeedChk(ierr);
238d7b241e6Sjeremylt   } else {
239d7b241e6Sjeremylt     blkindices = NULL;
240d7b241e6Sjeremylt   }
241d7b241e6Sjeremylt 
2424ce2993fSjeremylt   (*rstr)->ceed = ceed;
243d7b241e6Sjeremylt   ceed->refcount++;
2444ce2993fSjeremylt   (*rstr)->refcount = 1;
2454ce2993fSjeremylt   (*rstr)->nelem = nelem;
2464ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
2478795c945Sjeremylt   (*rstr)->nnodes = nnodes;
2484ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
2494ce2993fSjeremylt   (*rstr)->nblk = nblk;
2504ce2993fSjeremylt   (*rstr)->blksize = blksize;
251667bc5fcSjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
2524ce2993fSjeremylt          (const CeedInt *) blkindices, *rstr);
253d7b241e6Sjeremylt   CeedChk(ierr);
254d7b241e6Sjeremylt 
255d7b241e6Sjeremylt   if (cmode == CEED_OWN_POINTER)
256d7b241e6Sjeremylt     ierr = CeedFree(&indices); CeedChk(ierr);
257d7b241e6Sjeremylt 
258d7b241e6Sjeremylt   return 0;
259d7b241e6Sjeremylt }
260d7b241e6Sjeremylt 
261b11c1e72Sjeremylt /**
262b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
263b11c1e72Sjeremylt 
2644ce2993fSjeremylt   @param rstr  CeedElemRestriction
265b11c1e72Sjeremylt   @param lvec  The address of the L-vector to be created, or NULL
266b11c1e72Sjeremylt   @param evec  The address of the E-vector to be created, or NULL
267b11c1e72Sjeremylt 
268b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
269dfdf5a53Sjeremylt 
270dfdf5a53Sjeremylt   @ref Advanced
271b11c1e72Sjeremylt **/
2724ce2993fSjeremylt int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *lvec,
273d7b241e6Sjeremylt                                     CeedVector *evec) {
274d7b241e6Sjeremylt   int ierr;
275d7b241e6Sjeremylt   CeedInt n, m;
2768795c945Sjeremylt   m = rstr->nnodes * rstr->ncomp;
2774ce2993fSjeremylt   n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
278d7b241e6Sjeremylt   if (lvec) {
2794ce2993fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, m, lvec); CeedChk(ierr);
280d7b241e6Sjeremylt   }
281d7b241e6Sjeremylt   if (evec) {
2824ce2993fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, n, evec); CeedChk(ierr);
283d7b241e6Sjeremylt   }
284d7b241e6Sjeremylt   return 0;
285d7b241e6Sjeremylt }
286d7b241e6Sjeremylt 
287d7b241e6Sjeremylt /**
288b11c1e72Sjeremylt   @brief Restrict an L-vector to an E-vector or apply transpose
289d7b241e6Sjeremylt 
2904ce2993fSjeremylt   @param rstr    CeedElemRestriction
291d7b241e6Sjeremylt   @param tmode   Apply restriction or transpose
292d7b241e6Sjeremylt   @param lmode   Ordering of the ncomp components
2938795c945Sjeremylt   @param u       Input vector (of size @a nnodes * @a ncomp when
2948795c945Sjeremylt                    tmode=CEED_NOTRANSPOSE)
2958795c945Sjeremylt   @param v       Output vector (of size @a nelem * @a elemsize when
2968795c945Sjeremylt                    tmode=CEED_NOTRANSPOSE)
297d7b241e6Sjeremylt   @param request Request or CEED_REQUEST_IMMEDIATE
298b11c1e72Sjeremylt 
299b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
300dfdf5a53Sjeremylt 
301dfdf5a53Sjeremylt   @ref Advanced
302b11c1e72Sjeremylt **/
3034ce2993fSjeremylt int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode tmode,
304d7b241e6Sjeremylt                              CeedTransposeMode lmode,
305d7b241e6Sjeremylt                              CeedVector u, CeedVector v, CeedRequest *request) {
306d7b241e6Sjeremylt   CeedInt m,n;
307d7b241e6Sjeremylt   int ierr;
308d7b241e6Sjeremylt 
309d7b241e6Sjeremylt   if (tmode == CEED_NOTRANSPOSE) {
3104ce2993fSjeremylt     m = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
3118795c945Sjeremylt     n = rstr->nnodes * rstr->ncomp;
312d7b241e6Sjeremylt   } else {
3138795c945Sjeremylt     m = rstr->nnodes * rstr->ncomp;
3144ce2993fSjeremylt     n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
315d7b241e6Sjeremylt   }
316d7b241e6Sjeremylt   if (n != u->length)
317*c042f62fSJeremy L Thompson     // LCOV_EXCL_START
3184ce2993fSjeremylt     return CeedError(rstr->ceed, 2,
319d7b241e6Sjeremylt                      "Input vector size %d not compatible with element restriction (%d, %d)",
320d7b241e6Sjeremylt                      u->length, m, n);
321*c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
322d7b241e6Sjeremylt   if (m != v->length)
323*c042f62fSJeremy L Thompson     // LCOV_EXCL_START
3244ce2993fSjeremylt     return CeedError(rstr->ceed, 2,
325d7b241e6Sjeremylt                      "Output vector size %d not compatible with element restriction (%d, %d)",
326d7b241e6Sjeremylt                      v->length, m, n);
327*c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
3284ce2993fSjeremylt   ierr = rstr->Apply(rstr, tmode, lmode, u, v, request); CeedChk(ierr);
329d7b241e6Sjeremylt 
330d7b241e6Sjeremylt   return 0;
331d7b241e6Sjeremylt }
332d7b241e6Sjeremylt 
333d7b241e6Sjeremylt /**
334be9261b7Sjeremylt   @brief Restrict an L-vector to a block of an E-vector or apply transpose
335be9261b7Sjeremylt 
336be9261b7Sjeremylt   @param rstr    CeedElemRestriction
3371f37b403Sjeremylt   @param block   Block number to restrict to/from, i.e. block=0 will handle
3381f37b403Sjeremylt                  elements [0 : blksize] and block=3 will handle elements
3391f37b403Sjeremylt                  [3*blksize : 4*blksize]
340be9261b7Sjeremylt   @param tmode   Apply restriction or transpose
341be9261b7Sjeremylt   @param lmode   Ordering of the ncomp components
3428795c945Sjeremylt   @param u       Input vector (of size @a nnodes * @a ncomp when
3438795c945Sjeremylt                    tmode=CEED_NOTRANSPOSE)
3448795c945Sjeremylt   @param v       Output vector (of size @a nelem * @a elemsize when
3458795c945Sjeremylt                    tmode=CEED_NOTRANSPOSE)
346be9261b7Sjeremylt   @param request Request or CEED_REQUEST_IMMEDIATE
347be9261b7Sjeremylt 
348be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
349be9261b7Sjeremylt 
350be9261b7Sjeremylt   @ref Advanced
351be9261b7Sjeremylt **/
352be9261b7Sjeremylt int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block,
353be9261b7Sjeremylt                                   CeedTransposeMode tmode,
354be9261b7Sjeremylt                                   CeedTransposeMode lmode,
355be9261b7Sjeremylt                                   CeedVector u, CeedVector v,
356be9261b7Sjeremylt                                   CeedRequest *request) {
357be9261b7Sjeremylt   CeedInt m,n;
358be9261b7Sjeremylt   int ierr;
359be9261b7Sjeremylt 
360be9261b7Sjeremylt   if (tmode == CEED_NOTRANSPOSE) {
361be9261b7Sjeremylt     m = rstr->blksize * rstr->elemsize * rstr->ncomp;
3628795c945Sjeremylt     n = rstr->nnodes * rstr->ncomp;
363be9261b7Sjeremylt   } else {
3648795c945Sjeremylt     m = rstr->nnodes * rstr->ncomp;
365be9261b7Sjeremylt     n = rstr->blksize * rstr->elemsize * rstr->ncomp;
366be9261b7Sjeremylt   }
367be9261b7Sjeremylt   if (n != u->length)
368*c042f62fSJeremy L Thompson     // LCOV_EXCL_START
369be9261b7Sjeremylt     return CeedError(rstr->ceed, 2,
370be9261b7Sjeremylt                      "Input vector size %d not compatible with element restriction (%d, %d)",
371be9261b7Sjeremylt                      u->length, m, n);
372*c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
373be9261b7Sjeremylt   if (m != v->length)
374*c042f62fSJeremy L Thompson     // LCOV_EXCL_START
375be9261b7Sjeremylt     return CeedError(rstr->ceed, 2,
376be9261b7Sjeremylt                      "Output vector size %d not compatible with element restriction (%d, %d)",
377be9261b7Sjeremylt                      v->length, m, n);
378*c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
379be9261b7Sjeremylt   if (rstr->blksize*block > rstr->nelem)
380*c042f62fSJeremy L Thompson     // LCOV_EXCL_START
381be9261b7Sjeremylt     return CeedError(rstr->ceed, 2,
382be9261b7Sjeremylt                      "Cannot retrieve block %d, element %d > total elements %d",
383be9261b7Sjeremylt                      block, rstr->blksize*block, rstr->nelem);
384*c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
385be9261b7Sjeremylt   ierr = rstr->ApplyBlock(rstr, block, tmode, lmode, u, v, request);
386be9261b7Sjeremylt   CeedChk(ierr);
387be9261b7Sjeremylt 
388be9261b7Sjeremylt   return 0;
389be9261b7Sjeremylt }
390be9261b7Sjeremylt 
391be9261b7Sjeremylt /**
3921469ee4dSjeremylt   @brief Get the multiplicity of DoFs in a CeedElemRestriction
3931469ee4dSjeremylt 
3941469ee4dSjeremylt   @param rstr      CeedElemRestriction
3951469ee4dSjeremylt   @param[out] mult Vector to store multiplicity (of size ndof)
3961469ee4dSjeremylt 
3971469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
3981469ee4dSjeremylt 
3991469ee4dSjeremylt   @ref Advanced
4001469ee4dSjeremylt **/
4011469ee4dSjeremylt int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr,
4021469ee4dSjeremylt                                        CeedVector mult) {
4031469ee4dSjeremylt   int ierr;
4041469ee4dSjeremylt   CeedVector evec;
4051469ee4dSjeremylt 
4061469ee4dSjeremylt   // Create and set evec
4071469ee4dSjeremylt   ierr = CeedElemRestrictionCreateVector(rstr, NULL, &evec); CeedChk(ierr);
4081469ee4dSjeremylt   ierr = CeedVectorSetValue(evec, 1.0); CeedChk(ierr);
4091469ee4dSjeremylt 
4101469ee4dSjeremylt   // Apply to get multiplicity
4111469ee4dSjeremylt   ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, CEED_NOTRANSPOSE, evec,
4121469ee4dSjeremylt                                   mult, CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
4131469ee4dSjeremylt 
4141469ee4dSjeremylt   // Cleanup
4151469ee4dSjeremylt   ierr = CeedVectorDestroy(&evec); CeedChk(ierr);
4161469ee4dSjeremylt 
4171469ee4dSjeremylt   return 0;
4181469ee4dSjeremylt }
4191469ee4dSjeremylt 
4201469ee4dSjeremylt /**
4214ce2993fSjeremylt   @brief Get the Ceed associated with a CeedElemRestriction
4224ce2993fSjeremylt 
4234ce2993fSjeremylt   @param rstr             CeedElemRestriction
4244ce2993fSjeremylt   @param[out] ceed        Variable to store Ceed
4254ce2993fSjeremylt 
4264ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
4274ce2993fSjeremylt 
42823617272Sjeremylt   @ref Advanced
4294ce2993fSjeremylt **/
4304ce2993fSjeremylt int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
4314ce2993fSjeremylt   *ceed = rstr->ceed;
4324ce2993fSjeremylt   return 0;
4334ce2993fSjeremylt }
4344ce2993fSjeremylt 
4354ce2993fSjeremylt /**
436b11c1e72Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
437d7b241e6Sjeremylt 
4384ce2993fSjeremylt   @param rstr             CeedElemRestriction
439288c0443SJeremy L Thompson   @param[out] numelem     Variable to store number of elements
440b11c1e72Sjeremylt 
441b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
442dfdf5a53Sjeremylt 
44323617272Sjeremylt   @ref Advanced
444b11c1e72Sjeremylt **/
4454ce2993fSjeremylt int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
4464ce2993fSjeremylt                                       CeedInt *numelem) {
4474ce2993fSjeremylt   *numelem = rstr->nelem;
4484ce2993fSjeremylt   return 0;
4494ce2993fSjeremylt }
4504ce2993fSjeremylt 
4514ce2993fSjeremylt /**
4524ce2993fSjeremylt   @brief Get the size of elements in the CeedElemRestriction
4534ce2993fSjeremylt 
4544ce2993fSjeremylt   @param rstr             CeedElemRestriction
4554ce2993fSjeremylt   @param[out] elemsize    Variable to store size of elements
4564ce2993fSjeremylt 
4574ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
4584ce2993fSjeremylt 
45923617272Sjeremylt   @ref Advanced
4604ce2993fSjeremylt **/
4614ce2993fSjeremylt int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
4624ce2993fSjeremylt                                       CeedInt *elemsize) {
4634ce2993fSjeremylt   *elemsize = rstr->elemsize;
4644ce2993fSjeremylt   return 0;
4654ce2993fSjeremylt }
4664ce2993fSjeremylt 
4674ce2993fSjeremylt /**
4684ce2993fSjeremylt   @brief Get the number of degrees of freedom in the range of a
4694ce2993fSjeremylt          CeedElemRestriction
4704ce2993fSjeremylt 
4714ce2993fSjeremylt   @param rstr             CeedElemRestriction
4728795c945Sjeremylt   @param[out] numnodes    Variable to store number of nodes
4734ce2993fSjeremylt 
4744ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
4754ce2993fSjeremylt 
47623617272Sjeremylt   @ref Advanced
4774ce2993fSjeremylt **/
4788795c945Sjeremylt int CeedElemRestrictionGetNumNodes(CeedElemRestriction rstr,
4798795c945Sjeremylt                                    CeedInt *numnodes) {
4808795c945Sjeremylt   *numnodes = rstr->nnodes;
4814ce2993fSjeremylt   return 0;
4824ce2993fSjeremylt }
4834ce2993fSjeremylt 
4844ce2993fSjeremylt /**
4854ce2993fSjeremylt   @brief Get the number of components in the elements of a
4864ce2993fSjeremylt          CeedElemRestriction
4874ce2993fSjeremylt 
4884ce2993fSjeremylt   @param rstr             CeedElemRestriction
4894ce2993fSjeremylt   @param[out] numcomp     Variable to store number of components
4904ce2993fSjeremylt 
4914ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
4924ce2993fSjeremylt 
49323617272Sjeremylt   @ref Advanced
4944ce2993fSjeremylt **/
4954ce2993fSjeremylt int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
4964ce2993fSjeremylt                                         CeedInt *numcomp) {
4974ce2993fSjeremylt   *numcomp = rstr->ncomp;
4984ce2993fSjeremylt   return 0;
4994ce2993fSjeremylt }
5004ce2993fSjeremylt 
5014ce2993fSjeremylt /**
5024ce2993fSjeremylt   @brief Get the number of blocks in a CeedElemRestriction
5034ce2993fSjeremylt 
5044ce2993fSjeremylt   @param rstr             CeedElemRestriction
5054ce2993fSjeremylt   @param[out] numblock    Variable to store number of blocks
5064ce2993fSjeremylt 
5074ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5084ce2993fSjeremylt 
50923617272Sjeremylt   @ref Advanced
5104ce2993fSjeremylt **/
5114ce2993fSjeremylt int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
5124ce2993fSjeremylt                                     CeedInt *numblock) {
5134ce2993fSjeremylt   *numblock = rstr->nblk;
5144ce2993fSjeremylt   return 0;
5154ce2993fSjeremylt }
5164ce2993fSjeremylt 
5174ce2993fSjeremylt /**
5184ce2993fSjeremylt   @brief Get the size of blocks in the CeedElemRestriction
5194ce2993fSjeremylt 
520288c0443SJeremy L Thompson   @param rstr             CeedElemRestriction
5214ce2993fSjeremylt   @param[out] blksize     Variable to store size of blocks
5224ce2993fSjeremylt 
5234ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5244ce2993fSjeremylt 
52523617272Sjeremylt   @ref Advanced
5264ce2993fSjeremylt **/
5274ce2993fSjeremylt int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
5284ce2993fSjeremylt                                     CeedInt *blksize) {
5294ce2993fSjeremylt   *blksize = rstr->blksize;
5304ce2993fSjeremylt   return 0;
5314ce2993fSjeremylt }
5324ce2993fSjeremylt 
5334ce2993fSjeremylt /**
5344ce2993fSjeremylt   @brief Get the backend data of a CeedElemRestriction
5354ce2993fSjeremylt 
536288c0443SJeremy L Thompson   @param rstr             CeedElemRestriction
5374ce2993fSjeremylt   @param[out] data        Variable to store data
5384ce2993fSjeremylt 
5394ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5404ce2993fSjeremylt 
54123617272Sjeremylt   @ref Advanced
5424ce2993fSjeremylt **/
5434ce2993fSjeremylt int CeedElemRestrictionGetData(CeedElemRestriction rstr,
5444ce2993fSjeremylt                                void* *data) {
5454ce2993fSjeremylt   *data = rstr->data;
546d7b241e6Sjeremylt   return 0;
547d7b241e6Sjeremylt }
548d7b241e6Sjeremylt 
549d7b241e6Sjeremylt /**
550fe2413ffSjeremylt   @brief Set the backend data of a CeedElemRestriction
551fe2413ffSjeremylt 
552288c0443SJeremy L Thompson   @param[out] rstr        CeedElemRestriction
553fe2413ffSjeremylt   @param data             Data to set
554fe2413ffSjeremylt 
555fe2413ffSjeremylt   @return An error code: 0 - success, otherwise - failure
556fe2413ffSjeremylt 
557fe2413ffSjeremylt   @ref Advanced
558fe2413ffSjeremylt **/
559fe2413ffSjeremylt int CeedElemRestrictionSetData(CeedElemRestriction rstr,
560fe2413ffSjeremylt                                void* *data) {
561fe2413ffSjeremylt   rstr->data = *data;
562fe2413ffSjeremylt   return 0;
563fe2413ffSjeremylt }
564fe2413ffSjeremylt 
565fe2413ffSjeremylt /**
566f02ca4a2SJed Brown   @brief View a CeedElemRestriction
567f02ca4a2SJed Brown 
568f02ca4a2SJed Brown   @param[in] rstr CeedElemRestriction to view
569f02ca4a2SJed Brown   @param[in] stream Stream to write; typically stdout/stderr or a file
570f02ca4a2SJed Brown 
571f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
572f02ca4a2SJed Brown 
573f02ca4a2SJed Brown   @ref Utility
574f02ca4a2SJed Brown **/
575f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
576f02ca4a2SJed Brown   fprintf(stream,
577f02ca4a2SJed Brown           "CeedElemRestriction from (%d, %d) to %d elements with %d nodes each\n",
5788795c945Sjeremylt           rstr->nnodes, rstr->ncomp, rstr->nelem, rstr->elemsize);
579f02ca4a2SJed Brown   return 0;
580f02ca4a2SJed Brown }
581f02ca4a2SJed Brown 
582f02ca4a2SJed Brown /**
583b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
584b11c1e72Sjeremylt 
5854ce2993fSjeremylt   @param rstr CeedElemRestriction to destroy
586b11c1e72Sjeremylt 
587b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
588dfdf5a53Sjeremylt 
589dfdf5a53Sjeremylt   @ref Basic
590b11c1e72Sjeremylt **/
5914ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
592d7b241e6Sjeremylt   int ierr;
593d7b241e6Sjeremylt 
5944ce2993fSjeremylt   if (!*rstr || --(*rstr)->refcount > 0) return 0;
5954ce2993fSjeremylt   if ((*rstr)->Destroy) {
5964ce2993fSjeremylt     ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr);
597d7b241e6Sjeremylt   }
5984ce2993fSjeremylt   ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr);
5994ce2993fSjeremylt   ierr = CeedFree(rstr); CeedChk(ierr);
600d7b241e6Sjeremylt   return 0;
601d7b241e6Sjeremylt }
602d7b241e6Sjeremylt 
603d7b241e6Sjeremylt /// @}
604