xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-elemrestriction.c (revision 8621c6c6de0ebe428b5b7a9c1ff9e4a60667b9cc)
1 // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3 // reserved. See files LICENSE and NOTICE for details.
4 //
5 // This file is part of CEED, a collection of benchmarks, miniapps, software
6 // libraries and APIs for efficient high-order finite element and spectral
7 // element discretizations for exascale applications. For more information and
8 // source code availability see http://github.com/ceed.
9 //
10 // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11 // a collaborative effort of two U.S. Department of Energy organizations (Office
12 // of Science and the National Nuclear Security Administration) responsible for
13 // the planning and preparation of a capable exascale ecosystem, including
14 // software, applications, hardware, advanced system engineering and early
15 // testbed platforms, in support of the nation's exascale computing imperative.
16 
17 #include <ceed-impl.h>
18 #include <ceed-backend.h>
19 
20 /// @cond DOXYGEN_SKIP
21 static struct CeedElemRestriction_private ceed_elemrestriction_none;
22 /// @endcond
23 
24 /// @file
25 /// Implementation of public CeedElemRestriction interfaces
26 ///
27 /// @addtogroup CeedElemRestriction
28 /// @{
29 
30 /**
31   @brief Create a CeedElemRestriction
32 
33   @param ceed       A Ceed object where the CeedElemRestriction will be created
34   @param imode      Ordering of the ncomp components, i.e. it specifies
35                       the ordering of the components of the L-vector used
36                       by this CeedElemRestriction. CEED_NONINTERLACED indicates
37                       the component is the outermost index and CEED_INTERLACED
38                       indicates the component is the innermost index in
39                       ordering of the L-vector.
40   @param nelem      Number of elements described in the @a indices array
41   @param elemsize   Size (number of "nodes") per element
42   @param nnodes     The number of nodes in the L-vector. The input CeedVector
43                       to which the restriction will be applied is of size
44                       @a nnodes * @a ncomp. This size may include data
45                       used by other CeedElemRestriction objects describing
46                       different types of elements.
47   @param ncomp      Number of field components per interpolation node
48                       (1 for scalar fields)
49   @param mtype      Memory type of the @a indices array, see CeedMemType
50   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
51   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
52                       ordered list of the indices (into the input CeedVector)
53                       for the unknowns corresponding to element i, where
54                       0 <= i < @a nelem. All indices must be in the range
55                       [0, @a nnodes - 1].
56   @param[out] rstr  Address of the variable where the newly created
57                       CeedElemRestriction will be stored
58 
59   @return An error code: 0 - success, otherwise - failure
60 
61   @ref Basic
62 **/
63 int CeedElemRestrictionCreate(Ceed ceed, CeedInterlaceMode imode,
64                               CeedInt nelem, CeedInt elemsize, CeedInt nnodes,
65                               CeedInt ncomp, CeedMemType mtype,
66                               CeedCopyMode cmode, const CeedInt *indices,
67                               CeedElemRestriction *rstr) {
68   int ierr;
69 
70   if (!ceed->ElemRestrictionCreate) {
71     Ceed delegate;
72     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
73     CeedChk(ierr);
74 
75     if (!delegate)
76       // LCOV_EXCL_START
77       return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
78     // LCOV_EXCL_STOP
79 
80     ierr = CeedElemRestrictionCreate(delegate, imode, nelem, elemsize,
81                                      nnodes, ncomp, mtype, cmode,
82                                      indices, rstr); CeedChk(ierr);
83     return 0;
84   }
85 
86   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
87   (*rstr)->ceed = ceed;
88   ceed->refcount++;
89   (*rstr)->refcount = 1;
90   (*rstr)->imode = imode;
91   (*rstr)->nelem = nelem;
92   (*rstr)->elemsize = elemsize;
93   (*rstr)->nnodes = nnodes;
94   (*rstr)->ncomp = ncomp;
95   (*rstr)->nblk = nelem;
96   (*rstr)->blksize = 1;
97   ierr = ceed->ElemRestrictionCreate(mtype, cmode, indices, *rstr); CeedChk(ierr);
98   return 0;
99 }
100 
101 /**
102   @brief Create a strided CeedElemRestriction
103 
104   @param ceed       A Ceed object where the CeedElemRestriction will be created
105   @param nelem      Number of elements described by the restriction
106   @param elemsize   Size (number of "nodes") per element
107   @param nnodes     The number of nodes in the L-vector. The input CeedVector
108                       to which the restriction will be applied is of size
109                       @a nnodes * @a ncomp. This size may include data
110                       used by other CeedElemRestriction objects describing
111                       different types of elements.
112   @param ncomp      Number of field components per interpolation node
113                       (1 for scalar fields)
114   @param strides    Array for strides between [nodes, components, elements].
115                       The data for node i, component j, element k in the
116                       L-vector is given by
117                         i*strides[0] + j*strides[1] + k*strides[2]
118   @param rstr       Address of the variable where the newly created
119                       CeedElemRestriction will be stored
120 
121   @return An error code: 0 - success, otherwise - failure
122 
123   @ref Basic
124 **/
125 int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt nelem, CeedInt elemsize,
126                                      CeedInt nnodes, CeedInt ncomp,
127                                      const CeedInt strides[3],
128                                      CeedElemRestriction *rstr) {
129   int ierr;
130 
131   if (!ceed->ElemRestrictionCreate) {
132     Ceed delegate;
133     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
134     CeedChk(ierr);
135 
136     if (!delegate)
137       // LCOV_EXCL_START
138       return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
139     // LCOV_EXCL_STOP
140 
141     ierr = CeedElemRestrictionCreateStrided(delegate, nelem, elemsize, nnodes,
142                                             ncomp, strides, rstr); CeedChk(ierr);
143     return 0;
144   }
145 
146   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
147   (*rstr)->ceed = ceed;
148   ceed->refcount++;
149   (*rstr)->refcount = 1;
150   (*rstr)->nelem = nelem;
151   (*rstr)->elemsize = elemsize;
152   (*rstr)->nnodes = nnodes;
153   (*rstr)->ncomp = ncomp;
154   (*rstr)->nblk = nelem;
155   (*rstr)->blksize = 1;
156   ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr);
157   for (int i = 0; i<3; i++)
158     (*rstr)->strides[i] = strides[i];
159   ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL,
160                                      *rstr);
161   CeedChk(ierr);
162   return 0;
163 }
164 
165 /**
166   @brief Permute and pad indices for a blocked restriction
167 
168   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
169                       ordered list of the indices (into the input CeedVector)
170                       for the unknowns corresponding to element i, where
171                       0 <= i < @a nelem. All indices must be in the range
172                       [0, @a nnodes).
173   @param blkindices Array of permuted and padded indices of
174                       shape [@a nblk, @a elemsize, @a blksize].
175   @param nblk       Number of blocks
176   @param nelem      Number of elements
177   @param blksize    Number of elements in a block
178   @param elemsize   Size of each element
179 
180   @return An error code: 0 - success, otherwise - failure
181 
182   @ref Utility
183 **/
184 int CeedPermutePadIndices(const CeedInt *indices, CeedInt *blkindices,
185                           CeedInt nblk, CeedInt nelem, CeedInt blksize,
186                           CeedInt elemsize) {
187   for (CeedInt e = 0; e < nblk*blksize; e+=blksize)
188     for (int j = 0; j < blksize; j++)
189       for (int k = 0; k < elemsize; k++)
190         blkindices[e*elemsize + k*blksize + j]
191           = indices[CeedIntMin(e+j,nelem-1)*elemsize + k];
192   return 0;
193 }
194 
195 /**
196   @brief Create a blocked CeedElemRestriction, typically only called by backends
197 
198   @param ceed       A Ceed object where the CeedElemRestriction will be created.
199   @param imode      Ordering of the ncomp components, i.e. it specifies
200                       the ordering of the components of the L-vector used
201                       by this CeedElemRestriction. CEED_NONINTERLACED indicates
202                       the component is the outermost index and CEED_INTERLACED
203                       indicates the component is the innermost index in
204                       ordering of the L-vector.
205   @param nelem      Number of elements described in the @a indices array.
206   @param elemsize   Size (number of unknowns) per element
207   @param blksize    Number of elements in a block
208   @param nnodes     The number of nodes in the L-vector. The input CeedVector
209                       to which the restriction will be applied is of size
210                       @a nnodes * @a ncomp. This size may include data
211                       used by other CeedElemRestriction objects describing
212                       different types of elements.
213   @param ncomp      Number of field components per interpolation node
214                       (1 for scalar fields)
215   @param mtype      Memory type of the @a indices array, see CeedMemType
216   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
217   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
218                       ordered list of the indices (into the input CeedVector)
219                       for the unknowns corresponding to element i, where
220                       0 <= i < @a nelem. All indices must be in the range
221                       [0, @a nnodes). The backend will permute and pad this
222                       array to the desired ordering for the blocksize, which is
223                       typically given by the backend. The default reordering is
224                       to interlace elements.
225   @param rstr       Address of the variable where the newly created
226                       CeedElemRestriction will be stored
227 
228   @return An error code: 0 - success, otherwise - failure
229 
230   @ref Advanced
231  **/
232 int CeedElemRestrictionCreateBlocked(Ceed ceed,  CeedInterlaceMode imode,
233                                      CeedInt nelem, CeedInt elemsize,
234                                      CeedInt blksize, CeedInt nnodes,
235                                      CeedInt ncomp, CeedMemType mtype,
236                                      CeedCopyMode cmode, const CeedInt *indices,
237                                      CeedElemRestriction *rstr) {
238   int ierr;
239   CeedInt *blkindices;
240   CeedInt nblk = (nelem / blksize) + !!(nelem % blksize);
241 
242   if (!ceed->ElemRestrictionCreateBlocked) {
243     Ceed delegate;
244     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
245     CeedChk(ierr);
246 
247     if (!delegate)
248       // LCOV_EXCL_START
249       return CeedError(ceed, 1, "Backend does not support "
250                        "ElemRestrictionCreateBlocked");
251     // LCOV_EXCL_STOP
252 
253     ierr = CeedElemRestrictionCreateBlocked(delegate, imode, nelem, elemsize,
254                                             blksize, nnodes, ncomp, mtype, cmode,
255                                             indices, rstr); CeedChk(ierr);
256     return 0;
257   }
258 
259   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
260 
261   ierr = CeedCalloc(nblk*blksize*elemsize, &blkindices); CeedChk(ierr);
262   ierr = CeedPermutePadIndices(indices, blkindices, nblk, nelem, blksize,
263                                elemsize);
264   CeedChk(ierr);
265 
266   (*rstr)->ceed = ceed;
267   ceed->refcount++;
268   (*rstr)->refcount = 1;
269   (*rstr)->imode = imode;
270   (*rstr)->nelem = nelem;
271   (*rstr)->elemsize = elemsize;
272   (*rstr)->nnodes = nnodes;
273   (*rstr)->ncomp = ncomp;
274   (*rstr)->nblk = nblk;
275   (*rstr)->blksize = blksize;
276   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
277          (const CeedInt *) blkindices, *rstr); CeedChk(ierr);
278 
279   if (cmode == CEED_OWN_POINTER) {
280     ierr = CeedFree(&indices); CeedChk(ierr);
281   }
282 
283   return 0;
284 }
285 
286 /**
287   @brief Create a blocked strided CeedElemRestriction
288 
289   @param ceed       A Ceed object where the CeedElemRestriction will be created
290   @param nelem      Number of elements described by the restriction
291   @param elemsize   Size (number of "nodes") per element
292   @param blksize    Number of elements in a block
293   @param nnodes     The number of nodes in the L-vector. The input CeedVector
294                       to which the restriction will be applied is of size
295                       @a nnodes * @a ncomp. This size may include data
296                       used by other CeedElemRestriction objects describing
297                       different types of elements.
298   @param ncomp      Number of field components per interpolation node
299                       (1 for scalar fields)
300   @param strides    Array for strides between [nodes, components, elements].
301                       The data for node i, component j, element k in the
302                       L-vector is given by
303                         i*strides[0] + j*strides[1] + k*strides[2]
304   @param rstr       Address of the variable where the newly created
305                       CeedElemRestriction will be stored
306 
307   @return An error code: 0 - success, otherwise - failure
308 
309   @ref Basic
310 **/
311 int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt nelem,
312     CeedInt elemsize, CeedInt blksize, CeedInt nnodes, CeedInt ncomp,
313     const CeedInt strides[3], CeedElemRestriction *rstr) {
314   int ierr;
315   CeedInt nblk = (nelem / blksize) + !!(nelem % blksize);
316 
317   if (!ceed->ElemRestrictionCreateBlocked) {
318     Ceed delegate;
319     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
320     CeedChk(ierr);
321 
322     if (!delegate)
323       // LCOV_EXCL_START
324       return CeedError(ceed, 1, "Backend does not support "
325                        "ElemRestrictionCreateBlocked");
326     // LCOV_EXCL_STOP
327 
328     ierr = CeedElemRestrictionCreateBlockedStrided(delegate, nelem, elemsize,
329            blksize, nnodes, ncomp, strides, rstr);
330     CeedChk(ierr);
331     return 0;
332   }
333 
334   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
335 
336   (*rstr)->ceed = ceed;
337   ceed->refcount++;
338   (*rstr)->refcount = 1;
339   (*rstr)->nelem = nelem;
340   (*rstr)->elemsize = elemsize;
341   (*rstr)->nnodes = nnodes;
342   (*rstr)->ncomp = ncomp;
343   (*rstr)->nblk = nblk;
344   (*rstr)->blksize = blksize;
345   ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr);
346   for (int i = 0; i<3; i++)
347     (*rstr)->strides[i] = strides[i];
348   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
349          NULL, *rstr); CeedChk(ierr);
350 
351   return 0;
352 }
353 
354 /**
355   @brief Create CeedVectors associated with a CeedElemRestriction
356 
357   @param rstr  CeedElemRestriction
358   @param lvec  The address of the L-vector to be created, or NULL
359   @param evec  The address of the E-vector to be created, or NULL
360 
361   @return An error code: 0 - success, otherwise - failure
362 
363   @ref Advanced
364 **/
365 int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *lvec,
366                                     CeedVector *evec) {
367   int ierr;
368   CeedInt n, m;
369   m = rstr->nnodes * rstr->ncomp;
370   n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
371   if (lvec) {
372     ierr = CeedVectorCreate(rstr->ceed, m, lvec); CeedChk(ierr);
373   }
374   if (evec) {
375     ierr = CeedVectorCreate(rstr->ceed, n, evec); CeedChk(ierr);
376   }
377   return 0;
378 }
379 
380 /**
381   @brief Restrict an L-vector to an E-vector or apply its transpose
382 
383   @param rstr    CeedElemRestriction
384   @param tmode   Apply restriction or transpose
385   @param u       Input vector (of shape [@a nnodes, @a ncomp] when
386                    tmode=CEED_NOTRANSPOSE, imode=CEED_INTERLACED)
387   @param ru      Output vector (of shape [@a nelem * @a elemsize] when
388                    tmode=CEED_NOTRANSPOSE). Ordering of the e-vector is decided
389                    by the backend.
390   @param request Request or CEED_REQUEST_IMMEDIATE
391 
392   @return An error code: 0 - success, otherwise - failure
393 
394   @ref Advanced
395 **/
396 int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode tmode,
397                              CeedVector u, CeedVector ru,
398                              CeedRequest *request) {
399   CeedInt m,n;
400   int ierr;
401 
402   if (tmode == CEED_NOTRANSPOSE) {
403     m = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
404     n = rstr->nnodes * rstr->ncomp;
405   } else {
406     m = rstr->nnodes * rstr->ncomp;
407     n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
408   }
409   if (n != u->length)
410     // LCOV_EXCL_START
411     return CeedError(rstr->ceed, 2, "Input vector size %d not compatible with "
412                      "element restriction (%d, %d)", u->length, m, n);
413   // LCOV_EXCL_STOP
414   if (m != ru->length)
415     // LCOV_EXCL_START
416     return CeedError(rstr->ceed, 2, "Output vector size %d not compatible with "
417                      "element restriction (%d, %d)", ru->length, m, n);
418   // LCOV_EXCL_STOP
419   ierr = rstr->Apply(rstr, tmode, u, ru, request); CeedChk(ierr);
420 
421   return 0;
422 }
423 
424 /**
425   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
426 
427   @param rstr    CeedElemRestriction
428   @param block   Block number to restrict to/from, i.e. block=0 will handle
429                    elements [0 : blksize] and block=3 will handle elements
430                    [3*blksize : 4*blksize]
431   @param tmode   Apply restriction or transpose
432   @param u       Input vector (of shape [@a nnodes, @a ncomp] when
433                    tmode=CEED_NOTRANSPOSE, imode=CEED_INTERLACED)
434   @param ru      Output vector (of shape [@a blksize * @a elemsize] when
435                    tmode=CEED_NOTRANSPOSE). Ordering of the e-vector is decided
436                    by the backend.
437   @param request Request or CEED_REQUEST_IMMEDIATE
438 
439   @return An error code: 0 - success, otherwise - failure
440 
441   @ref Advanced
442 **/
443 int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block,
444                                   CeedTransposeMode tmode, CeedVector u,
445                                   CeedVector ru, CeedRequest *request) {
446   CeedInt m,n;
447   int ierr;
448 
449   if (tmode == CEED_NOTRANSPOSE) {
450     m = rstr->blksize * rstr->elemsize * rstr->ncomp;
451     n = rstr->nnodes * rstr->ncomp;
452   } else {
453     m = rstr->nnodes * rstr->ncomp;
454     n = rstr->blksize * rstr->elemsize * rstr->ncomp;
455   }
456   if (n != u->length)
457     // LCOV_EXCL_START
458     return CeedError(rstr->ceed, 2, "Input vector size %d not compatible with "
459                      "element restriction (%d, %d)", u->length, m, n);
460   // LCOV_EXCL_STOP
461   if (m != ru->length)
462     // LCOV_EXCL_START
463     return CeedError(rstr->ceed, 2, "Output vector size %d not compatible with "
464                      "element restriction (%d, %d)", ru->length, m, n);
465   // LCOV_EXCL_STOP
466   if (rstr->blksize*block > rstr->nelem)
467     // LCOV_EXCL_START
468     return CeedError(rstr->ceed, 2, "Cannot retrieve block %d, element %d > "
469                      "total elements %d", block, rstr->blksize*block,
470                      rstr->nelem);
471   // LCOV_EXCL_STOP
472   ierr = rstr->ApplyBlock(rstr, block, tmode, u, ru, request);
473   CeedChk(ierr);
474 
475   return 0;
476 }
477 
478 /**
479   @brief Get the multiplicity of nodes in a CeedElemRestriction
480 
481   @param rstr             CeedElemRestriction
482   @param[out] mult        Vector to store multiplicity (of size nnodes*ncomp)
483 
484   @return An error code: 0 - success, otherwise - failure
485 
486   @ref Advanced
487 **/
488 int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr,
489                                        CeedVector mult) {
490   int ierr;
491   CeedVector evec;
492 
493   // Create and set evec
494   ierr = CeedElemRestrictionCreateVector(rstr, NULL, &evec); CeedChk(ierr);
495   ierr = CeedVectorSetValue(evec, 1.0); CeedChk(ierr);
496   ierr = CeedVectorSetValue(mult, 0.0); CeedChk(ierr);
497 
498   // Apply to get multiplicity
499   ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, evec, mult,
500                                   CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
501 
502   // Cleanup
503   ierr = CeedVectorDestroy(&evec); CeedChk(ierr);
504 
505   return 0;
506 }
507 
508 /**
509   @brief Get the Ceed associated with a CeedElemRestriction
510 
511   @param rstr             CeedElemRestriction
512   @param[out] ceed        Variable to store Ceed
513 
514   @return An error code: 0 - success, otherwise - failure
515 
516   @ref Advanced
517 **/
518 int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
519   *ceed = rstr->ceed;
520   return 0;
521 }
522 
523 /**
524   @brief Get the L-vector interlaced mode of a CeedElemRestriction
525 
526   @param rstr             CeedElemRestriction
527   @param[out] imode       Variable to store imode
528 
529   @return An error code: 0 - success, otherwise - failure
530 
531   @ref Advanced
532 **/
533 int CeedElemRestrictionGetIMode(CeedElemRestriction rstr,
534                                 CeedInterlaceMode *imode) {
535   if (rstr->strides)
536     // LCOV_EXCL_START
537     return CeedError(rstr->ceed, 1, "Strided ElemRestriction has no interlace "
538                      "mode");
539   // LCOV_EXCL_STOP
540 
541   *imode = rstr->imode;
542   return 0;
543 }
544 
545 /**
546   @brief Get the total number of elements in the range of a CeedElemRestriction
547 
548   @param rstr             CeedElemRestriction
549   @param[out] numelem     Variable to store number of elements
550 
551   @return An error code: 0 - success, otherwise - failure
552 
553   @ref Advanced
554 **/
555 int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
556                                       CeedInt *numelem) {
557   *numelem = rstr->nelem;
558   return 0;
559 }
560 
561 /**
562   @brief Get the size of elements in the CeedElemRestriction
563 
564   @param rstr             CeedElemRestriction
565   @param[out] elemsize    Variable to store size of elements
566 
567   @return An error code: 0 - success, otherwise - failure
568 
569   @ref Advanced
570 **/
571 int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
572                                       CeedInt *elemsize) {
573   *elemsize = rstr->elemsize;
574   return 0;
575 }
576 
577 /**
578   @brief Get the number of degrees of freedom in the range of a
579          CeedElemRestriction
580 
581   @param rstr             CeedElemRestriction
582   @param[out] numnodes    Variable to store number of nodes
583 
584   @return An error code: 0 - success, otherwise - failure
585 
586   @ref Advanced
587 **/
588 int CeedElemRestrictionGetNumNodes(CeedElemRestriction rstr,
589                                    CeedInt *numnodes) {
590   *numnodes = rstr->nnodes;
591   return 0;
592 }
593 
594 /**
595   @brief Get the number of components in the elements of a
596          CeedElemRestriction
597 
598   @param rstr             CeedElemRestriction
599   @param[out] numcomp     Variable to store number of components
600 
601   @return An error code: 0 - success, otherwise - failure
602 
603   @ref Advanced
604 **/
605 int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
606                                         CeedInt *numcomp) {
607   *numcomp = rstr->ncomp;
608   return 0;
609 }
610 
611 /**
612   @brief Get the number of blocks in a CeedElemRestriction
613 
614   @param rstr             CeedElemRestriction
615   @param[out] numblock    Variable to store number of blocks
616 
617   @return An error code: 0 - success, otherwise - failure
618 
619   @ref Advanced
620 **/
621 int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
622                                     CeedInt *numblock) {
623   *numblock = rstr->nblk;
624   return 0;
625 }
626 
627 /**
628   @brief Get the size of blocks in the CeedElemRestriction
629 
630   @param rstr             CeedElemRestriction
631   @param[out] blksize     Variable to store size of blocks
632 
633   @return An error code: 0 - success, otherwise - failure
634 
635   @ref Advanced
636 **/
637 int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
638                                     CeedInt *blksize) {
639   *blksize = rstr->blksize;
640   return 0;
641 }
642 
643 /**
644   @brief Get the strides of a strided CeedElemRestriction
645 
646   @param rstr             CeedElemRestriction
647   @param[out] strides     Variable to store strides array
648 
649   @return An error code: 0 - success, otherwise - failure
650 
651   @ref Advanced
652 **/
653 int CeedElemRestrictionGetStrides(CeedElemRestriction rstr,
654                                   CeedInt (*strides)[3]) {
655   if (!rstr->strides)
656     // LCOV_EXCL_START
657     return CeedError(rstr->ceed, 1, "ElemRestriction has no stride data");
658   // LCOV_EXCL_STOP
659 
660   for (int i = 0; i<3; i++)
661     (*strides)[i] = rstr->strides[i];
662   return 0;
663 }
664 
665 /**
666   @brief Get the backend stride status of a CeedElemRestriction
667 
668   @param rstr             CeedElemRestriction
669   @param[out] bool        Variable to store stride status
670 
671   @return An error code: 0 - success, otherwise - failure
672 
673   @ref Advanced
674 **/
675 int CeedElemRestrictionGetBackendStridesStatus(CeedElemRestriction rstr,
676     bool *status) {
677   if (!rstr->strides)
678     // LCOV_EXCL_START
679     return CeedError(rstr->ceed, 1, "ElemRestriction has no stride data");
680   // LCOV_EXCL_STOP
681 
682   *status = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) &&
683              (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
684              (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
685   return 0;
686 }
687 
688 /**
689   @brief Get the backend data of a CeedElemRestriction
690 
691   @param rstr             CeedElemRestriction
692   @param[out] data        Variable to store data
693 
694   @return An error code: 0 - success, otherwise - failure
695 
696   @ref Advanced
697 **/
698 int CeedElemRestrictionGetData(CeedElemRestriction rstr, void **data) {
699   *data = rstr->data;
700   return 0;
701 }
702 
703 /**
704   @brief Set the backend data of a CeedElemRestriction
705 
706   @param[out] rstr        CeedElemRestriction
707   @param data             Data to set
708 
709   @return An error code: 0 - success, otherwise - failure
710 
711   @ref Advanced
712 **/
713 int CeedElemRestrictionSetData(CeedElemRestriction rstr, void **data) {
714   rstr->data = *data;
715   return 0;
716 }
717 
718 /**
719   @brief View a CeedElemRestriction
720 
721   @param[in] rstr    CeedElemRestriction to view
722   @param[in] stream  Stream to write; typically stdout/stderr or a file
723 
724   @return Error code: 0 - success, otherwise - failure
725 
726   @ref Utility
727 **/
728 int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
729   char stridesstr[500];
730   if (rstr->strides)
731     sprintf(stridesstr, "[%d, %d, %d]", rstr->strides[0], rstr->strides[1],
732             rstr->strides[2]);
733 
734   fprintf(stream, "%sCeedElemRestriction from (%d, %d) to %d elements with %d "
735           "nodes each and %s %s\n", rstr->blksize > 1 ? "Blocked " : "",
736           rstr->nnodes, rstr->ncomp, rstr->nelem, rstr->elemsize,
737           rstr->strides ? "strides" : "L-vector components",
738           rstr->strides ? stridesstr : CeedInterlaceModes[rstr->imode]);
739   return 0;
740 }
741 
742 /**
743   @brief Destroy a CeedElemRestriction
744 
745   @param rstr  CeedElemRestriction to destroy
746 
747   @return An error code: 0 - success, otherwise - failure
748 
749   @ref Basic
750 **/
751 int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
752   int ierr;
753 
754   if (!*rstr || --(*rstr)->refcount > 0)
755     return 0;
756   if ((*rstr)->Destroy) {
757     ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr);
758   }
759   ierr = CeedFree(&(*rstr)->strides); CeedChk(ierr);
760   ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr);
761   ierr = CeedFree(rstr); CeedChk(ierr);
762   return 0;
763 }
764 
765 /// @cond DOXYGEN_SKIP
766 // Indicate that the stride is determined by the backend
767 CeedInt CEED_STRIDES_BACKEND[3] = {};
768 
769 // Indicate that no ElemRestriction is provided by the user
770 CeedElemRestriction CEED_ELEMRESTRICTION_NONE = &ceed_elemrestriction_none;
771 /// @endcond
772 
773 /// @}
774