xref: /libCEED/interface/ceed-elemrestriction.c (revision efc78312550893c11c7921bf7c4699a3e027cc68)
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
3895bb1877Svaleriabarra                       (1 for scalar fields)
39b11c1e72Sjeremylt   @param mtype      Memory type of the @a indices array, see CeedMemType
40b11c1e72Sjeremylt   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
418795c945Sjeremylt   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
428795c945Sjeremylt                       ordered list of the indices (into the input CeedVector)
438795c945Sjeremylt                       for the unknowns corresponding to element i, where
4434138859Sjeremylt                       0 <= i < @a nelem. All indices must be in the range
4523e8ed12Sjeremylt                       [0, @a nnodes - 1].
464ce2993fSjeremylt   @param[out] rstr  Address of the variable where the newly created
47b11c1e72Sjeremylt                       CeedElemRestriction will be stored
48d7b241e6Sjeremylt 
49b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
50dfdf5a53Sjeremylt 
51dfdf5a53Sjeremylt   @ref Basic
52b11c1e72Sjeremylt **/
53d7b241e6Sjeremylt int CeedElemRestrictionCreate(Ceed ceed, CeedInt nelem, CeedInt elemsize,
548795c945Sjeremylt                               CeedInt nnodes, CeedInt ncomp, CeedMemType mtype,
55d7b241e6Sjeremylt                               CeedCopyMode cmode, const CeedInt *indices,
564ce2993fSjeremylt                               CeedElemRestriction *rstr) {
57d7b241e6Sjeremylt   int ierr;
58d7b241e6Sjeremylt 
595fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
605fe0d4faSjeremylt     Ceed delegate;
61aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
62aefd8378Sjeremylt     CeedChk(ierr);
635fe0d4faSjeremylt 
645fe0d4faSjeremylt     if (!delegate)
65c042f62fSJeremy L Thompson       // LCOV_EXCL_START
66d7b241e6Sjeremylt       return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
67c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
685fe0d4faSjeremylt 
695fe0d4faSjeremylt     ierr = CeedElemRestrictionCreate(delegate, nelem, elemsize,
708795c945Sjeremylt                                      nnodes, ncomp, mtype, cmode,
714ce2993fSjeremylt                                      indices, rstr); CeedChk(ierr);
725fe0d4faSjeremylt     return 0;
735fe0d4faSjeremylt   }
745fe0d4faSjeremylt 
754ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
764ce2993fSjeremylt   (*rstr)->ceed = ceed;
77d7b241e6Sjeremylt   ceed->refcount++;
784ce2993fSjeremylt   (*rstr)->refcount = 1;
794ce2993fSjeremylt   (*rstr)->nelem = nelem;
804ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
818795c945Sjeremylt   (*rstr)->nnodes = nnodes;
824ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
834ce2993fSjeremylt   (*rstr)->nblk = nelem;
844ce2993fSjeremylt   (*rstr)->blksize = 1;
854ce2993fSjeremylt   ierr = ceed->ElemRestrictionCreate(mtype, cmode, indices, *rstr); CeedChk(ierr);
86d7b241e6Sjeremylt   return 0;
87d7b241e6Sjeremylt }
88d7b241e6Sjeremylt 
89d7b241e6Sjeremylt /**
90b11c1e72Sjeremylt   @brief Create an identity CeedElemRestriction
91d7b241e6Sjeremylt 
92b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
93b11c1e72Sjeremylt   @param nelem      Number of elements described in the @a indices array
94b11c1e72Sjeremylt   @param elemsize   Size (number of "nodes") per element
958795c945Sjeremylt   @param nnodes     The number of nodes in the L-vector. The input CeedVector
968795c945Sjeremylt                       to which the restriction will be applied is of size
978795c945Sjeremylt                       @a nnodes * @a ncomp. This size may include data
98d7b241e6Sjeremylt                       used by other CeedElemRestriction objects describing
998795c945Sjeremylt                       different types of elements.
100b11c1e72Sjeremylt   @param ncomp      Number of field components per interpolation node
10195bb1877Svaleriabarra                       (1 for scalar fields)
1024ce2993fSjeremylt   @param rstr       Address of the variable where the newly created
103b11c1e72Sjeremylt                       CeedElemRestriction will be stored
104d7b241e6Sjeremylt 
105b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
106dfdf5a53Sjeremylt 
107dfdf5a53Sjeremylt   @ref Basic
108b11c1e72Sjeremylt **/
1094b8bea3bSJed Brown int CeedElemRestrictionCreateIdentity(Ceed ceed, CeedInt nelem,
110f90c8643Sjeremylt                                       CeedInt elemsize, CeedInt nnodes,
111f90c8643Sjeremylt                                       CeedInt ncomp,
112f90c8643Sjeremylt                                       CeedElemRestriction *rstr) {
113d7b241e6Sjeremylt   int ierr;
114d7b241e6Sjeremylt 
1155fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
1165fe0d4faSjeremylt     Ceed delegate;
117aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
118aefd8378Sjeremylt     CeedChk(ierr);
1195fe0d4faSjeremylt 
1205fe0d4faSjeremylt     if (!delegate)
121c042f62fSJeremy L Thompson       // LCOV_EXCL_START
1221d102b48SJeremy L Thompson       return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
123c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
1245fe0d4faSjeremylt 
1255fe0d4faSjeremylt     ierr = CeedElemRestrictionCreateIdentity(delegate, nelem, elemsize,
1268795c945Sjeremylt            nnodes, ncomp, rstr); CeedChk(ierr);
1275fe0d4faSjeremylt     return 0;
1285fe0d4faSjeremylt   }
1295fe0d4faSjeremylt 
1304ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
1314ce2993fSjeremylt   (*rstr)->ceed = ceed;
132d7b241e6Sjeremylt   ceed->refcount++;
1334ce2993fSjeremylt   (*rstr)->refcount = 1;
1344ce2993fSjeremylt   (*rstr)->nelem = nelem;
1354ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
1368795c945Sjeremylt   (*rstr)->nnodes = nnodes;
1374ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
1384ce2993fSjeremylt   (*rstr)->nblk = nelem;
1394ce2993fSjeremylt   (*rstr)->blksize = 1;
1401dfeef1dSjeremylt   ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL,
1411dfeef1dSjeremylt                                      *rstr);
1424b8bea3bSJed Brown   CeedChk(ierr);
143d7b241e6Sjeremylt   return 0;
144d7b241e6Sjeremylt }
145d7b241e6Sjeremylt 
146d7b241e6Sjeremylt /**
147b11c1e72Sjeremylt   @brief Permute and pad indices for a blocked restriction
148d7b241e6Sjeremylt 
1498795c945Sjeremylt   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
1508795c945Sjeremylt                       ordered list of the indices (into the input CeedVector)
1518795c945Sjeremylt                       for the unknowns corresponding to element i, where
15234138859Sjeremylt                       0 <= i < @a nelem. All indices must be in the range
1538795c945Sjeremylt                       [0, @a nnodes).
154ecf6354eSJed Brown   @param blkindices Array of permuted and padded indices of
155ecf6354eSJed Brown                       shape [@a nblk, @a elemsize, @a blksize].
156d7b241e6Sjeremylt   @param nblk       Number of blocks
157d7b241e6Sjeremylt   @param nelem      Number of elements
158d7b241e6Sjeremylt   @param blksize    Number of elements in a block
159d7b241e6Sjeremylt   @param elemsize   Size of each element
160d7b241e6Sjeremylt 
161b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
162b11c1e72Sjeremylt 
163dfdf5a53Sjeremylt   @ref Utility
164b11c1e72Sjeremylt **/
165dfdf5a53Sjeremylt int CeedPermutePadIndices(const CeedInt *indices, CeedInt *blkindices,
166692c2638Sjeremylt                           CeedInt nblk, CeedInt nelem, CeedInt blksize,
167692c2638Sjeremylt                           CeedInt elemsize) {
168d7b241e6Sjeremylt   for (CeedInt e = 0; e < nblk*blksize; e+=blksize)
169d7b241e6Sjeremylt     for (int j = 0; j < blksize; j++)
170d7b241e6Sjeremylt       for (int k = 0; k < elemsize; k++)
171d7b241e6Sjeremylt         blkindices[e*elemsize + k*blksize + j]
172d7b241e6Sjeremylt           = indices[CeedIntMin(e+j,nelem-1)*elemsize + k];
173dfdf5a53Sjeremylt   return 0;
174d7b241e6Sjeremylt }
175d7b241e6Sjeremylt 
176d7b241e6Sjeremylt /**
177b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
178d7b241e6Sjeremylt 
179d7b241e6Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created.
180d7b241e6Sjeremylt   @param nelem      Number of elements described in the @a indices array.
181b11c1e72Sjeremylt   @param elemsize   Size (number of unknowns) per element
182b11c1e72Sjeremylt   @param blksize    Number of elements in a block
1838795c945Sjeremylt   @param nnodes     The number of nodes in the L-vector. The input CeedVector
1848795c945Sjeremylt                       to which the restriction will be applied is of size
1858795c945Sjeremylt                       @a nnodes * @a ncomp. This size may include data
186d7b241e6Sjeremylt                       used by other CeedElemRestriction objects describing
187d7b241e6Sjeremylt                       different types of elements.
18895bb1877Svaleriabarra   @param ncomp      Number of field components per interpolation node
18995bb1877Svaleriabarra                       (1 for scalar fields)
190b11c1e72Sjeremylt   @param mtype      Memory type of the @a indices array, see CeedMemType
191b11c1e72Sjeremylt   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
1928795c945Sjeremylt   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
1938795c945Sjeremylt                       ordered list of the indices (into the input CeedVector)
1948795c945Sjeremylt                       for the unknowns corresponding to element i, where
19534138859Sjeremylt                       0 <= i < @a nelem. All indices must be in the range
1968795c945Sjeremylt                       [0, @a nnodes). The backend will permute and pad this
1978795c945Sjeremylt                       array to the desired ordering for the blocksize, which is
1988795c945Sjeremylt                       typically given by the backend. The default reordering is
1998795c945Sjeremylt                       to interlace elements.
2004ce2993fSjeremylt   @param rstr       Address of the variable where the newly created
201b11c1e72Sjeremylt                       CeedElemRestriction will be stored
202d7b241e6Sjeremylt 
203b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
204dfdf5a53Sjeremylt 
205dfdf5a53Sjeremylt   @ref Advanced
206b11c1e72Sjeremylt  **/
207d7b241e6Sjeremylt int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt nelem, CeedInt elemsize,
2088795c945Sjeremylt                                      CeedInt blksize, CeedInt nnodes,
2098795c945Sjeremylt                                      CeedInt ncomp, CeedMemType mtype,
2108795c945Sjeremylt                                      CeedCopyMode cmode, const CeedInt *indices,
2114ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
212d7b241e6Sjeremylt   int ierr;
213d7b241e6Sjeremylt   CeedInt *blkindices;
214d7b241e6Sjeremylt   CeedInt nblk = (nelem / blksize) + !!(nelem % blksize);
215d7b241e6Sjeremylt 
2165fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
2175fe0d4faSjeremylt     Ceed delegate;
218aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
219aefd8378Sjeremylt     CeedChk(ierr);
2205fe0d4faSjeremylt 
2215fe0d4faSjeremylt     if (!delegate)
222c042f62fSJeremy L Thompson       // LCOV_EXCL_START
2231d102b48SJeremy L Thompson       return CeedError(ceed, 1, "Backend does not support "
2241d102b48SJeremy L Thompson                        "ElemRestrictionCreateBlocked");
225c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
2265fe0d4faSjeremylt 
2275fe0d4faSjeremylt     ierr = CeedElemRestrictionCreateBlocked(delegate, nelem, elemsize,
2288795c945Sjeremylt                                             blksize, nnodes, ncomp, mtype, cmode,
2294ce2993fSjeremylt                                             indices, rstr); CeedChk(ierr);
2305fe0d4faSjeremylt     return 0;
2315fe0d4faSjeremylt   }
232d7b241e6Sjeremylt 
2334ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
234d7b241e6Sjeremylt 
235d7b241e6Sjeremylt   if (indices) {
236de686571SJeremy L Thompson     ierr = CeedCalloc(nblk*blksize*elemsize, &blkindices); CeedChk(ierr);
2374b8bea3bSJed Brown     ierr = CeedPermutePadIndices(indices, blkindices, nblk, nelem, blksize,
2384b8bea3bSJed Brown                                  elemsize);
239dfdf5a53Sjeremylt     CeedChk(ierr);
240d7b241e6Sjeremylt   } else {
241d7b241e6Sjeremylt     blkindices = NULL;
242d7b241e6Sjeremylt   }
243d7b241e6Sjeremylt 
2444ce2993fSjeremylt   (*rstr)->ceed = ceed;
245d7b241e6Sjeremylt   ceed->refcount++;
2464ce2993fSjeremylt   (*rstr)->refcount = 1;
2474ce2993fSjeremylt   (*rstr)->nelem = nelem;
2484ce2993fSjeremylt   (*rstr)->elemsize = elemsize;
2498795c945Sjeremylt   (*rstr)->nnodes = nnodes;
2504ce2993fSjeremylt   (*rstr)->ncomp = ncomp;
2514ce2993fSjeremylt   (*rstr)->nblk = nblk;
2524ce2993fSjeremylt   (*rstr)->blksize = blksize;
253667bc5fcSjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
2547f823360Sjeremylt          (const CeedInt *) blkindices, *rstr); CeedChk(ierr);
255d7b241e6Sjeremylt 
2561d102b48SJeremy L Thompson   if (cmode == CEED_OWN_POINTER) {
257d7b241e6Sjeremylt     ierr = CeedFree(&indices); CeedChk(ierr);
2581d102b48SJeremy L Thompson   }
259d7b241e6Sjeremylt 
260d7b241e6Sjeremylt   return 0;
261d7b241e6Sjeremylt }
262d7b241e6Sjeremylt 
263b11c1e72Sjeremylt /**
264b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
265b11c1e72Sjeremylt 
2664ce2993fSjeremylt   @param rstr  CeedElemRestriction
267b11c1e72Sjeremylt   @param lvec  The address of the L-vector to be created, or NULL
268b11c1e72Sjeremylt   @param evec  The address of the E-vector to be created, or NULL
269b11c1e72Sjeremylt 
270b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
271dfdf5a53Sjeremylt 
272dfdf5a53Sjeremylt   @ref Advanced
273b11c1e72Sjeremylt **/
2744ce2993fSjeremylt int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *lvec,
275d7b241e6Sjeremylt                                     CeedVector *evec) {
276d7b241e6Sjeremylt   int ierr;
277d7b241e6Sjeremylt   CeedInt n, m;
2788795c945Sjeremylt   m = rstr->nnodes * rstr->ncomp;
2794ce2993fSjeremylt   n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
280d7b241e6Sjeremylt   if (lvec) {
2814ce2993fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, m, lvec); CeedChk(ierr);
282d7b241e6Sjeremylt   }
283d7b241e6Sjeremylt   if (evec) {
2844ce2993fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, n, evec); CeedChk(ierr);
285d7b241e6Sjeremylt   }
286d7b241e6Sjeremylt   return 0;
287d7b241e6Sjeremylt }
288d7b241e6Sjeremylt 
289d7b241e6Sjeremylt /**
290d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
291d7b241e6Sjeremylt 
2924ce2993fSjeremylt   @param rstr    CeedElemRestriction
293d7b241e6Sjeremylt   @param tmode   Apply restriction or transpose
294d9e1f99aSValeria Barra   @param lmode   Ordering of the ncomp components, i.e. it specifies
295d9e1f99aSValeria Barra                    the ordering of the components of the l-vector used
296d9e1f99aSValeria Barra                    by this CeedElemRestriction. CEED_NOTRANSPOSE indicates
297d9e1f99aSValeria Barra                    the component is the outermost index and CEED_TRANSPOSE
298d9e1f99aSValeria Barra                    indicates the component is the innermost index in
299d9e1f99aSValeria Barra                    ordering of the l-vector
3007aaeacdcSjeremylt   @param u       Input vector (of shape [@a nnodes, @a ncomp] when
3017aaeacdcSjeremylt                    tmode=CEED_NOTRANSPOSE, lmode=CEED_TRANSPOSE)
3027aaeacdcSjeremylt   @param v       Output vector (of shape [@a nelem * @a elemsize] when
3037aaeacdcSjeremylt                    tmode=CEED_NOTRANSPOSE). Ordering of the e-vector is decided
3047aaeacdcSjeremylt                    by the backend.
305d7b241e6Sjeremylt   @param request Request or CEED_REQUEST_IMMEDIATE
306b11c1e72Sjeremylt 
307b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
308dfdf5a53Sjeremylt 
309dfdf5a53Sjeremylt   @ref Advanced
310b11c1e72Sjeremylt **/
3114ce2993fSjeremylt int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode tmode,
312692c2638Sjeremylt                              CeedTransposeMode lmode, CeedVector u,
313692c2638Sjeremylt                              CeedVector v, CeedRequest *request) {
314d7b241e6Sjeremylt   CeedInt m,n;
315d7b241e6Sjeremylt   int ierr;
316d7b241e6Sjeremylt 
317d7b241e6Sjeremylt   if (tmode == CEED_NOTRANSPOSE) {
3184ce2993fSjeremylt     m = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
3198795c945Sjeremylt     n = rstr->nnodes * rstr->ncomp;
320d7b241e6Sjeremylt   } else {
3218795c945Sjeremylt     m = rstr->nnodes * rstr->ncomp;
3224ce2993fSjeremylt     n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
323d7b241e6Sjeremylt   }
324d7b241e6Sjeremylt   if (n != u->length)
325c042f62fSJeremy L Thompson     // LCOV_EXCL_START
3261d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Input vector size %d not compatible with "
3271d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
328c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
329d7b241e6Sjeremylt   if (m != v->length)
330c042f62fSJeremy L Thompson     // LCOV_EXCL_START
3311d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Output vector size %d not compatible with "
3321d102b48SJeremy L Thompson                      "element restriction (%d, %d)", v->length, m, n);
333c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
3344ce2993fSjeremylt   ierr = rstr->Apply(rstr, tmode, lmode, u, v, request); CeedChk(ierr);
335d7b241e6Sjeremylt 
336d7b241e6Sjeremylt   return 0;
337d7b241e6Sjeremylt }
338d7b241e6Sjeremylt 
339d7b241e6Sjeremylt /**
340d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
341be9261b7Sjeremylt 
342be9261b7Sjeremylt   @param rstr    CeedElemRestriction
3431f37b403Sjeremylt   @param block   Block number to restrict to/from, i.e. block=0 will handle
3441f37b403Sjeremylt                    elements [0 : blksize] and block=3 will handle elements
3451f37b403Sjeremylt                    [3*blksize : 4*blksize]
346be9261b7Sjeremylt   @param tmode   Apply restriction or transpose
347d9e1f99aSValeria Barra   @param lmode   Ordering of the ncomp components, i.e. it specifies
348d9e1f99aSValeria Barra                    the ordering of the components of the l-vector used
349d9e1f99aSValeria Barra                    by this CeedElemRestriction. CEED_NOTRANSPOSE indicates
350d9e1f99aSValeria Barra                    the component is the outermost index and CEED_TRANSPOSE
351d9e1f99aSValeria Barra                    indicates the component is the innermost index in
352d9e1f99aSValeria Barra                    ordering of the l-vector
3537aaeacdcSjeremylt   @param u       Input vector (of shape [@a nnodes, @a ncomp] when
3547aaeacdcSjeremylt                    tmode=CEED_NOTRANSPOSE, lmode=CEED_TRANSPOSE)
3557aaeacdcSjeremylt   @param v       Output vector (of shape [@a blksize * @a elemsize] when
3567aaeacdcSjeremylt                    tmode=CEED_NOTRANSPOSE). Ordering of the e-vector is decided
3577aaeacdcSjeremylt                    by the backend.
358be9261b7Sjeremylt   @param request Request or CEED_REQUEST_IMMEDIATE
359be9261b7Sjeremylt 
360be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
361be9261b7Sjeremylt 
362be9261b7Sjeremylt   @ref Advanced
363be9261b7Sjeremylt **/
364be9261b7Sjeremylt int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block,
365be9261b7Sjeremylt                                   CeedTransposeMode tmode,
366692c2638Sjeremylt                                   CeedTransposeMode lmode, CeedVector u,
367692c2638Sjeremylt                                   CeedVector v, CeedRequest *request) {
368be9261b7Sjeremylt   CeedInt m,n;
369be9261b7Sjeremylt   int ierr;
370be9261b7Sjeremylt 
371be9261b7Sjeremylt   if (tmode == CEED_NOTRANSPOSE) {
372be9261b7Sjeremylt     m = rstr->blksize * rstr->elemsize * rstr->ncomp;
3738795c945Sjeremylt     n = rstr->nnodes * rstr->ncomp;
374be9261b7Sjeremylt   } else {
3758795c945Sjeremylt     m = rstr->nnodes * rstr->ncomp;
376be9261b7Sjeremylt     n = rstr->blksize * rstr->elemsize * rstr->ncomp;
377be9261b7Sjeremylt   }
378be9261b7Sjeremylt   if (n != u->length)
379c042f62fSJeremy L Thompson     // LCOV_EXCL_START
3801d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Input vector size %d not compatible with "
3811d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
382c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
383be9261b7Sjeremylt   if (m != v->length)
384c042f62fSJeremy L Thompson     // LCOV_EXCL_START
3851d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Output vector size %d not compatible with "
3861d102b48SJeremy L Thompson                      "element restriction (%d, %d)", v->length, m, n);
387c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
388be9261b7Sjeremylt   if (rstr->blksize*block > rstr->nelem)
389c042f62fSJeremy L Thompson     // LCOV_EXCL_START
3901d102b48SJeremy L Thompson     return CeedError(rstr->ceed, 2, "Cannot retrieve block %d, element %d > "
3911d102b48SJeremy L Thompson                      "total elements %d", block, rstr->blksize*block,
3921d102b48SJeremy L Thompson                      rstr->nelem);
393c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
394be9261b7Sjeremylt   ierr = rstr->ApplyBlock(rstr, block, tmode, lmode, u, v, request);
395be9261b7Sjeremylt   CeedChk(ierr);
396be9261b7Sjeremylt 
397be9261b7Sjeremylt   return 0;
398be9261b7Sjeremylt }
399be9261b7Sjeremylt 
400be9261b7Sjeremylt /**
401d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
4021469ee4dSjeremylt 
4031469ee4dSjeremylt   @param rstr             CeedElemRestriction
404*efc78312Sjeremylt   @param lmode            Ordering of the ncomp components, i.e. it specifies
405*efc78312Sjeremylt                             the ordering of the components of the l-vector used
406*efc78312Sjeremylt                             by this CeedElemRestriction. CEED_NOTRANSPOSE
407*efc78312Sjeremylt                             indicates the component is the outermost index and
408*efc78312Sjeremylt                             CEED_TRANSPOSE indicates the component is the
409*efc78312Sjeremylt                             innermost index in ordering of the l-vector
410d9e1f99aSValeria Barra   @param[out] mult        Vector to store multiplicity (of size nnodes)
4111469ee4dSjeremylt 
4121469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
4131469ee4dSjeremylt 
4141469ee4dSjeremylt   @ref Advanced
4151469ee4dSjeremylt **/
4161469ee4dSjeremylt int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr,
417*efc78312Sjeremylt                                        CeedTransposeMode lmode,
4181469ee4dSjeremylt                                        CeedVector mult) {
4191469ee4dSjeremylt   int ierr;
4201469ee4dSjeremylt   CeedVector evec;
4211469ee4dSjeremylt 
4221469ee4dSjeremylt   // Create and set evec
4231469ee4dSjeremylt   ierr = CeedElemRestrictionCreateVector(rstr, NULL, &evec); CeedChk(ierr);
4241469ee4dSjeremylt   ierr = CeedVectorSetValue(evec, 1.0); CeedChk(ierr);
4251469ee4dSjeremylt 
4261469ee4dSjeremylt   // Apply to get multiplicity
427*efc78312Sjeremylt   ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, lmode, evec, mult,
428*efc78312Sjeremylt                                   CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
4291469ee4dSjeremylt 
4301469ee4dSjeremylt   // Cleanup
4311469ee4dSjeremylt   ierr = CeedVectorDestroy(&evec); CeedChk(ierr);
4321469ee4dSjeremylt 
4331469ee4dSjeremylt   return 0;
4341469ee4dSjeremylt }
4351469ee4dSjeremylt 
4361469ee4dSjeremylt /**
4374ce2993fSjeremylt   @brief Get the Ceed associated with a CeedElemRestriction
4384ce2993fSjeremylt 
4394ce2993fSjeremylt   @param rstr             CeedElemRestriction
4404ce2993fSjeremylt   @param[out] ceed        Variable to store Ceed
4414ce2993fSjeremylt 
4424ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
4434ce2993fSjeremylt 
44423617272Sjeremylt   @ref Advanced
4454ce2993fSjeremylt **/
4464ce2993fSjeremylt int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
4474ce2993fSjeremylt   *ceed = rstr->ceed;
4484ce2993fSjeremylt   return 0;
4494ce2993fSjeremylt }
4504ce2993fSjeremylt 
4514ce2993fSjeremylt /**
452b11c1e72Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
453d7b241e6Sjeremylt 
4544ce2993fSjeremylt   @param rstr             CeedElemRestriction
455288c0443SJeremy L Thompson   @param[out] numelem     Variable to store number of elements
456b11c1e72Sjeremylt 
457b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
458dfdf5a53Sjeremylt 
45923617272Sjeremylt   @ref Advanced
460b11c1e72Sjeremylt **/
4614ce2993fSjeremylt int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
4624ce2993fSjeremylt                                       CeedInt *numelem) {
4634ce2993fSjeremylt   *numelem = rstr->nelem;
4644ce2993fSjeremylt   return 0;
4654ce2993fSjeremylt }
4664ce2993fSjeremylt 
4674ce2993fSjeremylt /**
4684ce2993fSjeremylt   @brief Get the size of elements in the CeedElemRestriction
4694ce2993fSjeremylt 
4704ce2993fSjeremylt   @param rstr             CeedElemRestriction
4714ce2993fSjeremylt   @param[out] elemsize    Variable to store size of elements
4724ce2993fSjeremylt 
4734ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
4744ce2993fSjeremylt 
47523617272Sjeremylt   @ref Advanced
4764ce2993fSjeremylt **/
4774ce2993fSjeremylt int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
4784ce2993fSjeremylt                                       CeedInt *elemsize) {
4794ce2993fSjeremylt   *elemsize = rstr->elemsize;
4804ce2993fSjeremylt   return 0;
4814ce2993fSjeremylt }
4824ce2993fSjeremylt 
4834ce2993fSjeremylt /**
4844ce2993fSjeremylt   @brief Get the number of degrees of freedom in the range of a
4854ce2993fSjeremylt          CeedElemRestriction
4864ce2993fSjeremylt 
4874ce2993fSjeremylt   @param rstr             CeedElemRestriction
4888795c945Sjeremylt   @param[out] numnodes    Variable to store number of nodes
4894ce2993fSjeremylt 
4904ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
4914ce2993fSjeremylt 
49223617272Sjeremylt   @ref Advanced
4934ce2993fSjeremylt **/
4948795c945Sjeremylt int CeedElemRestrictionGetNumNodes(CeedElemRestriction rstr,
4958795c945Sjeremylt                                    CeedInt *numnodes) {
4968795c945Sjeremylt   *numnodes = rstr->nnodes;
4974ce2993fSjeremylt   return 0;
4984ce2993fSjeremylt }
4994ce2993fSjeremylt 
5004ce2993fSjeremylt /**
5014ce2993fSjeremylt   @brief Get the number of components in the elements of a
5024ce2993fSjeremylt          CeedElemRestriction
5034ce2993fSjeremylt 
5044ce2993fSjeremylt   @param rstr             CeedElemRestriction
5054ce2993fSjeremylt   @param[out] numcomp     Variable to store number of components
5064ce2993fSjeremylt 
5074ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5084ce2993fSjeremylt 
50923617272Sjeremylt   @ref Advanced
5104ce2993fSjeremylt **/
5114ce2993fSjeremylt int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
5124ce2993fSjeremylt                                         CeedInt *numcomp) {
5134ce2993fSjeremylt   *numcomp = rstr->ncomp;
5144ce2993fSjeremylt   return 0;
5154ce2993fSjeremylt }
5164ce2993fSjeremylt 
5174ce2993fSjeremylt /**
5184ce2993fSjeremylt   @brief Get the number of blocks in a CeedElemRestriction
5194ce2993fSjeremylt 
5204ce2993fSjeremylt   @param rstr             CeedElemRestriction
5214ce2993fSjeremylt   @param[out] numblock    Variable to store number of blocks
5224ce2993fSjeremylt 
5234ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5244ce2993fSjeremylt 
52523617272Sjeremylt   @ref Advanced
5264ce2993fSjeremylt **/
5274ce2993fSjeremylt int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
5284ce2993fSjeremylt                                     CeedInt *numblock) {
5294ce2993fSjeremylt   *numblock = rstr->nblk;
5304ce2993fSjeremylt   return 0;
5314ce2993fSjeremylt }
5324ce2993fSjeremylt 
5334ce2993fSjeremylt /**
5344ce2993fSjeremylt   @brief Get the size of blocks in the CeedElemRestriction
5354ce2993fSjeremylt 
536288c0443SJeremy L Thompson   @param rstr             CeedElemRestriction
5374ce2993fSjeremylt   @param[out] blksize     Variable to store size of blocks
5384ce2993fSjeremylt 
5394ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5404ce2993fSjeremylt 
54123617272Sjeremylt   @ref Advanced
5424ce2993fSjeremylt **/
5434ce2993fSjeremylt int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
5444ce2993fSjeremylt                                     CeedInt *blksize) {
5454ce2993fSjeremylt   *blksize = rstr->blksize;
5464ce2993fSjeremylt   return 0;
5474ce2993fSjeremylt }
5484ce2993fSjeremylt 
5494ce2993fSjeremylt /**
5504ce2993fSjeremylt   @brief Get the backend data of a CeedElemRestriction
5514ce2993fSjeremylt 
552288c0443SJeremy L Thompson   @param rstr             CeedElemRestriction
5534ce2993fSjeremylt   @param[out] data        Variable to store data
5544ce2993fSjeremylt 
5554ce2993fSjeremylt   @return An error code: 0 - success, otherwise - failure
5564ce2993fSjeremylt 
55723617272Sjeremylt   @ref Advanced
5584ce2993fSjeremylt **/
5591d102b48SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void **data) {
5604ce2993fSjeremylt   *data = rstr->data;
561d7b241e6Sjeremylt   return 0;
562d7b241e6Sjeremylt }
563d7b241e6Sjeremylt 
564d7b241e6Sjeremylt /**
565fe2413ffSjeremylt   @brief Set the backend data of a CeedElemRestriction
566fe2413ffSjeremylt 
567288c0443SJeremy L Thompson   @param[out] rstr        CeedElemRestriction
568fe2413ffSjeremylt   @param data             Data to set
569fe2413ffSjeremylt 
570fe2413ffSjeremylt   @return An error code: 0 - success, otherwise - failure
571fe2413ffSjeremylt 
572fe2413ffSjeremylt   @ref Advanced
573fe2413ffSjeremylt **/
5741d102b48SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void **data) {
575fe2413ffSjeremylt   rstr->data = *data;
576fe2413ffSjeremylt   return 0;
577fe2413ffSjeremylt }
578fe2413ffSjeremylt 
579fe2413ffSjeremylt /**
580f02ca4a2SJed Brown   @brief View a CeedElemRestriction
581f02ca4a2SJed Brown 
582f02ca4a2SJed Brown   @param[in] rstr    CeedElemRestriction to view
583f02ca4a2SJed Brown   @param[in] stream  Stream to write; typically stdout/stderr or a file
584f02ca4a2SJed Brown 
585f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
586f02ca4a2SJed Brown 
587f02ca4a2SJed Brown   @ref Utility
588f02ca4a2SJed Brown **/
589f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
5901d102b48SJeremy L Thompson   fprintf(stream, "CeedElemRestriction from (%d, %d) to %d elements with %d "
5911d102b48SJeremy L Thompson           "nodes each\n", rstr->nnodes, rstr->ncomp, rstr->nelem,
5921d102b48SJeremy L Thompson           rstr->elemsize);
593f02ca4a2SJed Brown   return 0;
594f02ca4a2SJed Brown }
595f02ca4a2SJed Brown 
596f02ca4a2SJed Brown /**
597b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
598b11c1e72Sjeremylt 
5994ce2993fSjeremylt   @param rstr  CeedElemRestriction to destroy
600b11c1e72Sjeremylt 
601b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
602dfdf5a53Sjeremylt 
603dfdf5a53Sjeremylt   @ref Basic
604b11c1e72Sjeremylt **/
6054ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
606d7b241e6Sjeremylt   int ierr;
607d7b241e6Sjeremylt 
6081d102b48SJeremy L Thompson   if (!*rstr || --(*rstr)->refcount > 0)
6091d102b48SJeremy L Thompson     return 0;
6104ce2993fSjeremylt   if ((*rstr)->Destroy) {
6114ce2993fSjeremylt     ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr);
612d7b241e6Sjeremylt   }
6134ce2993fSjeremylt   ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr);
6144ce2993fSjeremylt   ierr = CeedFree(rstr); CeedChk(ierr);
615d7b241e6Sjeremylt   return 0;
616d7b241e6Sjeremylt }
617d7b241e6Sjeremylt 
618d7b241e6Sjeremylt /// @}
619