xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-elemrestriction.c (revision 61dbc9d25335c1a7855bdb901ed4d560d51eee1f)
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 /// @file
21 /// Implementation of public CeedElemRestriction interfaces
22 ///
23 /// @addtogroup CeedElemRestriction
24 /// @{
25 
26 /**
27   @brief Create a CeedElemRestriction
28 
29   @param ceed       A Ceed object where the CeedElemRestriction will be created
30   @param imode      Ordering of the ncomp components, i.e. it specifies
31                       the ordering of the components of the L-vector used
32                       by this CeedElemRestriction. CEED_NONINTERLACED indicates
33                       the component is the outermost index and CEED_INTERLACED
34                       indicates the component is the innermost index in
35                       ordering of the L-vector.
36   @param nelem      Number of elements described in the @a indices array
37   @param elemsize   Size (number of "nodes") per element
38   @param nnodes     The number of nodes in the L-vector. The input CeedVector
39                       to which the restriction will be applied is of size
40                       @a nnodes * @a ncomp. This size may include data
41                       used by other CeedElemRestriction objects describing
42                       different types of elements.
43   @param ncomp      Number of field components per interpolation node
44                       (1 for scalar fields)
45   @param mtype      Memory type of the @a indices array, see CeedMemType
46   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
47   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
48                       ordered list of the indices (into the input CeedVector)
49                       for the unknowns corresponding to element i, where
50                       0 <= i < @a nelem. All indices must be in the range
51                       [0, @a nnodes - 1].
52   @param[out] rstr  Address of the variable where the newly created
53                       CeedElemRestriction will be stored
54 
55   @return An error code: 0 - success, otherwise - failure
56 
57   @ref Basic
58 **/
59 int CeedElemRestrictionCreate(Ceed ceed,  CeedInterlaceMode imode,
60                               CeedInt nelem,
61                               CeedInt elemsize, CeedInt nnodes, CeedInt ncomp,
62                               CeedMemType mtype, CeedCopyMode cmode,
63                               const CeedInt *indices,
64                               CeedElemRestriction *rstr) {
65   int ierr;
66 
67   if (!ceed->ElemRestrictionCreate) {
68     Ceed delegate;
69     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
70     CeedChk(ierr);
71 
72     if (!delegate)
73       // LCOV_EXCL_START
74       return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
75     // LCOV_EXCL_STOP
76 
77     ierr = CeedElemRestrictionCreate(delegate, imode, nelem, elemsize,
78                                      nnodes, ncomp, mtype, cmode,
79                                      indices, rstr); CeedChk(ierr);
80     return 0;
81   }
82 
83   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
84   (*rstr)->ceed = ceed;
85   ceed->refcount++;
86   (*rstr)->refcount = 1;
87   (*rstr)->imode = imode;
88   (*rstr)->nelem = nelem;
89   (*rstr)->elemsize = elemsize;
90   (*rstr)->nnodes = nnodes;
91   (*rstr)->ncomp = ncomp;
92   (*rstr)->nblk = nelem;
93   (*rstr)->blksize = 1;
94   ierr = ceed->ElemRestrictionCreate(mtype, cmode, indices, *rstr); CeedChk(ierr);
95   return 0;
96 }
97 
98 /**
99   @brief Create an identity CeedElemRestriction
100 
101   @param ceed       A Ceed object where the CeedElemRestriction will be created
102   @param imode      Ordering of the ncomp components, i.e. it specifies
103                       the ordering of the components of the L-vector used
104                       by this CeedElemRestriction. CEED_NONINTERLACED indicates
105                       the component is the outermost index and CEED_INTERLACED
106                       indicates the component is the innermost index in
107                       ordering of the L-vector.
108   @param nelem      Number of elements described in the @a indices array
109   @param elemsize   Size (number of "nodes") per element
110   @param nnodes     The number of nodes in the L-vector. The input CeedVector
111                       to which the restriction will be applied is of size
112                       @a nnodes * @a ncomp. This size may include data
113                       used by other CeedElemRestriction objects describing
114                       different types of elements.
115   @param ncomp      Number of field components per interpolation node
116                       (1 for scalar fields)
117   @param rstr       Address of the variable where the newly created
118                       CeedElemRestriction will be stored
119 
120   @return An error code: 0 - success, otherwise - failure
121 
122   @ref Basic
123 **/
124 int CeedElemRestrictionCreateIdentity(Ceed ceed,  CeedInterlaceMode imode,
125                                       CeedInt nelem, CeedInt elemsize,
126                                       CeedInt nnodes, CeedInt ncomp,
127                                       CeedElemRestriction *rstr) {
128   int ierr;
129 
130   if (!ceed->ElemRestrictionCreate) {
131     Ceed delegate;
132     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
133     CeedChk(ierr);
134 
135     if (!delegate)
136       // LCOV_EXCL_START
137       return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
138     // LCOV_EXCL_STOP
139 
140     ierr = CeedElemRestrictionCreateIdentity(delegate, imode, nelem, elemsize,
141            nnodes, ncomp, rstr); CeedChk(ierr);
142     return 0;
143   }
144 
145   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
146   (*rstr)->ceed = ceed;
147   ceed->refcount++;
148   (*rstr)->refcount = 1;
149   (*rstr)->imode = imode;
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 = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL,
157                                      *rstr);
158   CeedChk(ierr);
159   return 0;
160 }
161 
162 /**
163   @brief Permute and pad indices for a blocked restriction
164 
165   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
166                       ordered list of the indices (into the input CeedVector)
167                       for the unknowns corresponding to element i, where
168                       0 <= i < @a nelem. All indices must be in the range
169                       [0, @a nnodes).
170   @param blkindices Array of permuted and padded indices of
171                       shape [@a nblk, @a elemsize, @a blksize].
172   @param nblk       Number of blocks
173   @param nelem      Number of elements
174   @param blksize    Number of elements in a block
175   @param elemsize   Size of each element
176 
177   @return An error code: 0 - success, otherwise - failure
178 
179   @ref Utility
180 **/
181 int CeedPermutePadIndices(const CeedInt *indices, CeedInt *blkindices,
182                           CeedInt nblk, CeedInt nelem, CeedInt blksize,
183                           CeedInt elemsize) {
184   for (CeedInt e = 0; e < nblk*blksize; e+=blksize)
185     for (int j = 0; j < blksize; j++)
186       for (int k = 0; k < elemsize; k++)
187         blkindices[e*elemsize + k*blksize + j]
188           = indices[CeedIntMin(e+j,nelem-1)*elemsize + k];
189   return 0;
190 }
191 
192 /**
193   @brief Create a blocked CeedElemRestriction, typically only called by backends
194 
195   @param ceed       A Ceed object where the CeedElemRestriction will be created.
196   @param imode      Ordering of the ncomp components, i.e. it specifies
197                       the ordering of the components of the L-vector used
198                       by this CeedElemRestriction. CEED_NONINTERLACED indicates
199                       the component is the outermost index and CEED_INTERLACED
200                       indicates the component is the innermost index in
201                       ordering of the L-vector.
202   @param nelem      Number of elements described in the @a indices array.
203   @param elemsize   Size (number of unknowns) per element
204   @param blksize    Number of elements in a block
205   @param nnodes     The number of nodes in the L-vector. The input CeedVector
206                       to which the restriction will be applied is of size
207                       @a nnodes * @a ncomp. This size may include data
208                       used by other CeedElemRestriction objects describing
209                       different types of elements.
210   @param ncomp      Number of field components per interpolation node
211                       (1 for scalar fields)
212   @param mtype      Memory type of the @a indices array, see CeedMemType
213   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
214   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the
215                       ordered list of the indices (into the input CeedVector)
216                       for the unknowns corresponding to element i, where
217                       0 <= i < @a nelem. All indices must be in the range
218                       [0, @a nnodes). The backend will permute and pad this
219                       array to the desired ordering for the blocksize, which is
220                       typically given by the backend. The default reordering is
221                       to interlace elements.
222   @param rstr       Address of the variable where the newly created
223                       CeedElemRestriction will be stored
224 
225   @return An error code: 0 - success, otherwise - failure
226 
227   @ref Advanced
228  **/
229 int CeedElemRestrictionCreateBlocked(Ceed ceed,  CeedInterlaceMode imode,
230                                      CeedInt nelem, CeedInt elemsize,
231                                      CeedInt blksize, CeedInt nnodes,
232                                      CeedInt ncomp, CeedMemType mtype,
233                                      CeedCopyMode cmode, const CeedInt *indices,
234                                      CeedElemRestriction *rstr) {
235   int ierr;
236   CeedInt *blkindices;
237   CeedInt nblk = (nelem / blksize) + !!(nelem % blksize);
238 
239   if (!ceed->ElemRestrictionCreateBlocked) {
240     Ceed delegate;
241     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
242     CeedChk(ierr);
243 
244     if (!delegate)
245       // LCOV_EXCL_START
246       return CeedError(ceed, 1, "Backend does not support "
247                        "ElemRestrictionCreateBlocked");
248     // LCOV_EXCL_STOP
249 
250     ierr = CeedElemRestrictionCreateBlocked(delegate, imode, nelem, elemsize,
251                                             blksize, nnodes, ncomp, mtype, cmode,
252                                             indices, rstr); CeedChk(ierr);
253     return 0;
254   }
255 
256   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
257 
258   if (indices) {
259     ierr = CeedCalloc(nblk*blksize*elemsize, &blkindices); CeedChk(ierr);
260     ierr = CeedPermutePadIndices(indices, blkindices, nblk, nelem, blksize,
261                                  elemsize);
262     CeedChk(ierr);
263   } else {
264     blkindices = NULL;
265   }
266 
267   (*rstr)->ceed = ceed;
268   ceed->refcount++;
269   (*rstr)->refcount = 1;
270   (*rstr)->imode = imode;
271   (*rstr)->nelem = nelem;
272   (*rstr)->elemsize = elemsize;
273   (*rstr)->nnodes = nnodes;
274   (*rstr)->ncomp = ncomp;
275   (*rstr)->nblk = nblk;
276   (*rstr)->blksize = blksize;
277   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
278          (const CeedInt *) blkindices, *rstr); CeedChk(ierr);
279 
280   if (cmode == CEED_OWN_POINTER) {
281     ierr = CeedFree(&indices); CeedChk(ierr);
282   }
283 
284   return 0;
285 }
286 
287 /**
288   @brief Create CeedVectors associated with a CeedElemRestriction
289 
290   @param rstr  CeedElemRestriction
291   @param lvec  The address of the L-vector to be created, or NULL
292   @param evec  The address of the E-vector to be created, or NULL
293 
294   @return An error code: 0 - success, otherwise - failure
295 
296   @ref Advanced
297 **/
298 int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *lvec,
299                                     CeedVector *evec) {
300   int ierr;
301   CeedInt n, m;
302   m = rstr->nnodes * rstr->ncomp;
303   n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
304   if (lvec) {
305     ierr = CeedVectorCreate(rstr->ceed, m, lvec); CeedChk(ierr);
306   }
307   if (evec) {
308     ierr = CeedVectorCreate(rstr->ceed, n, evec); CeedChk(ierr);
309   }
310   return 0;
311 }
312 
313 /**
314   @brief Restrict an L-vector to an E-vector or apply its transpose
315 
316   @param rstr    CeedElemRestriction
317   @param tmode   Apply restriction or transpose
318   @param u       Input vector (of shape [@a nnodes, @a ncomp] when
319                    tmode=CEED_NOTRANSPOSE, imode=CEED_INTERLACED)
320   @param ru      Output vector (of shape [@a nelem * @a elemsize] when
321                    tmode=CEED_NOTRANSPOSE). Ordering of the e-vector is decided
322                    by the backend.
323   @param request Request or CEED_REQUEST_IMMEDIATE
324 
325   @return An error code: 0 - success, otherwise - failure
326 
327   @ref Advanced
328 **/
329 int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode tmode,
330                              CeedVector u, CeedVector ru,
331                              CeedRequest *request) {
332   CeedInt m,n;
333   int ierr;
334 
335   if (tmode == CEED_NOTRANSPOSE) {
336     m = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
337     n = rstr->nnodes * rstr->ncomp;
338   } else {
339     m = rstr->nnodes * rstr->ncomp;
340     n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
341   }
342   if (n != u->length)
343     // LCOV_EXCL_START
344     return CeedError(rstr->ceed, 2, "Input vector size %d not compatible with "
345                      "element restriction (%d, %d)", u->length, m, n);
346   // LCOV_EXCL_STOP
347   if (m != ru->length)
348     // LCOV_EXCL_START
349     return CeedError(rstr->ceed, 2, "Output vector size %d not compatible with "
350                      "element restriction (%d, %d)", ru->length, m, n);
351   // LCOV_EXCL_STOP
352   ierr = rstr->Apply(rstr, tmode, u, ru, request); CeedChk(ierr);
353 
354   return 0;
355 }
356 
357 /**
358   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
359 
360   @param rstr    CeedElemRestriction
361   @param block   Block number to restrict to/from, i.e. block=0 will handle
362                    elements [0 : blksize] and block=3 will handle elements
363                    [3*blksize : 4*blksize]
364   @param tmode   Apply restriction or transpose
365   @param u       Input vector (of shape [@a nnodes, @a ncomp] when
366                    tmode=CEED_NOTRANSPOSE, imode=CEED_INTERLACED)
367   @param ru      Output vector (of shape [@a blksize * @a elemsize] when
368                    tmode=CEED_NOTRANSPOSE). Ordering of the e-vector is decided
369                    by the backend.
370   @param request Request or CEED_REQUEST_IMMEDIATE
371 
372   @return An error code: 0 - success, otherwise - failure
373 
374   @ref Advanced
375 **/
376 int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block,
377                                   CeedTransposeMode tmode, CeedVector u,
378                                   CeedVector ru, CeedRequest *request) {
379   CeedInt m,n;
380   int ierr;
381 
382   if (tmode == CEED_NOTRANSPOSE) {
383     m = rstr->blksize * rstr->elemsize * rstr->ncomp;
384     n = rstr->nnodes * rstr->ncomp;
385   } else {
386     m = rstr->nnodes * rstr->ncomp;
387     n = rstr->blksize * rstr->elemsize * rstr->ncomp;
388   }
389   if (n != u->length)
390     // LCOV_EXCL_START
391     return CeedError(rstr->ceed, 2, "Input vector size %d not compatible with "
392                      "element restriction (%d, %d)", u->length, m, n);
393   // LCOV_EXCL_STOP
394   if (m != ru->length)
395     // LCOV_EXCL_START
396     return CeedError(rstr->ceed, 2, "Output vector size %d not compatible with "
397                      "element restriction (%d, %d)", ru->length, m, n);
398   // LCOV_EXCL_STOP
399   if (rstr->blksize*block > rstr->nelem)
400     // LCOV_EXCL_START
401     return CeedError(rstr->ceed, 2, "Cannot retrieve block %d, element %d > "
402                      "total elements %d", block, rstr->blksize*block,
403                      rstr->nelem);
404   // LCOV_EXCL_STOP
405   ierr = rstr->ApplyBlock(rstr, block, tmode, u, ru, request);
406   CeedChk(ierr);
407 
408   return 0;
409 }
410 
411 /**
412   @brief Get the multiplicity of nodes in a CeedElemRestriction
413 
414   @param rstr             CeedElemRestriction
415   @param[out] mult        Vector to store multiplicity (of size nnodes)
416 
417   @return An error code: 0 - success, otherwise - failure
418 
419   @ref Advanced
420 **/
421 int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr,
422                                        CeedVector mult) {
423   int ierr;
424   CeedVector evec;
425 
426   // Create and set evec
427   ierr = CeedElemRestrictionCreateVector(rstr, NULL, &evec); CeedChk(ierr);
428   ierr = CeedVectorSetValue(evec, 1.0); CeedChk(ierr);
429 
430   // Apply to get multiplicity
431   ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, evec, mult,
432                                   CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
433 
434   // Cleanup
435   ierr = CeedVectorDestroy(&evec); CeedChk(ierr);
436 
437   return 0;
438 }
439 
440 /**
441   @brief Get the Ceed associated with a CeedElemRestriction
442 
443   @param rstr             CeedElemRestriction
444   @param[out] ceed        Variable to store Ceed
445 
446   @return An error code: 0 - success, otherwise - failure
447 
448   @ref Advanced
449 **/
450 int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
451   *ceed = rstr->ceed;
452   return 0;
453 }
454 
455 /**
456   @brief Get the L-vector interlaced mode of a CeedElemRestriction
457 
458   @param rstr             CeedElemRestriction
459   @param[out] imode       Variable to store imode
460 
461   @return An error code: 0 - success, otherwise - failure
462 
463   @ref Advanced
464 **/
465 int CeedElemRestrictionGetIMode(CeedElemRestriction rstr,
466                                 CeedInterlaceMode *imode) {
467   *imode = rstr->imode;
468   return 0;
469 }
470 
471 /**
472   @brief Get the total number of elements in the range of a CeedElemRestriction
473 
474   @param rstr             CeedElemRestriction
475   @param[out] numelem     Variable to store number of elements
476 
477   @return An error code: 0 - success, otherwise - failure
478 
479   @ref Advanced
480 **/
481 int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
482                                       CeedInt *numelem) {
483   *numelem = rstr->nelem;
484   return 0;
485 }
486 
487 /**
488   @brief Get the size of elements in the CeedElemRestriction
489 
490   @param rstr             CeedElemRestriction
491   @param[out] elemsize    Variable to store size of elements
492 
493   @return An error code: 0 - success, otherwise - failure
494 
495   @ref Advanced
496 **/
497 int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
498                                       CeedInt *elemsize) {
499   *elemsize = rstr->elemsize;
500   return 0;
501 }
502 
503 /**
504   @brief Get the number of degrees of freedom in the range of a
505          CeedElemRestriction
506 
507   @param rstr             CeedElemRestriction
508   @param[out] numnodes    Variable to store number of nodes
509 
510   @return An error code: 0 - success, otherwise - failure
511 
512   @ref Advanced
513 **/
514 int CeedElemRestrictionGetNumNodes(CeedElemRestriction rstr,
515                                    CeedInt *numnodes) {
516   *numnodes = rstr->nnodes;
517   return 0;
518 }
519 
520 /**
521   @brief Get the number of components in the elements of a
522          CeedElemRestriction
523 
524   @param rstr             CeedElemRestriction
525   @param[out] numcomp     Variable to store number of components
526 
527   @return An error code: 0 - success, otherwise - failure
528 
529   @ref Advanced
530 **/
531 int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
532                                         CeedInt *numcomp) {
533   *numcomp = rstr->ncomp;
534   return 0;
535 }
536 
537 /**
538   @brief Get the number of blocks in a CeedElemRestriction
539 
540   @param rstr             CeedElemRestriction
541   @param[out] numblock    Variable to store number of blocks
542 
543   @return An error code: 0 - success, otherwise - failure
544 
545   @ref Advanced
546 **/
547 int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
548                                     CeedInt *numblock) {
549   *numblock = rstr->nblk;
550   return 0;
551 }
552 
553 /**
554   @brief Get the size of blocks in the CeedElemRestriction
555 
556   @param rstr             CeedElemRestriction
557   @param[out] blksize     Variable to store size of blocks
558 
559   @return An error code: 0 - success, otherwise - failure
560 
561   @ref Advanced
562 **/
563 int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
564                                     CeedInt *blksize) {
565   *blksize = rstr->blksize;
566   return 0;
567 }
568 
569 /**
570   @brief Get the backend data of a CeedElemRestriction
571 
572   @param rstr             CeedElemRestriction
573   @param[out] data        Variable to store data
574 
575   @return An error code: 0 - success, otherwise - failure
576 
577   @ref Advanced
578 **/
579 int CeedElemRestrictionGetData(CeedElemRestriction rstr, void **data) {
580   *data = rstr->data;
581   return 0;
582 }
583 
584 /**
585   @brief Set the backend data of a CeedElemRestriction
586 
587   @param[out] rstr        CeedElemRestriction
588   @param data             Data to set
589 
590   @return An error code: 0 - success, otherwise - failure
591 
592   @ref Advanced
593 **/
594 int CeedElemRestrictionSetData(CeedElemRestriction rstr, void **data) {
595   rstr->data = *data;
596   return 0;
597 }
598 
599 /**
600   @brief View a CeedElemRestriction
601 
602   @param[in] rstr    CeedElemRestriction to view
603   @param[in] stream  Stream to write; typically stdout/stderr or a file
604 
605   @return Error code: 0 - success, otherwise - failure
606 
607   @ref Utility
608 **/
609 int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
610   fprintf(stream, "CeedElemRestriction from (%d, %d) to %d elements with %d "
611           "nodes each and L-vector components %s\n", rstr->nnodes, rstr->ncomp,
612           rstr->nelem, rstr->elemsize, CeedInterlaceModes[rstr->imode]);
613   return 0;
614 }
615 
616 /**
617   @brief Destroy a CeedElemRestriction
618 
619   @param rstr  CeedElemRestriction to destroy
620 
621   @return An error code: 0 - success, otherwise - failure
622 
623   @ref Basic
624 **/
625 int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
626   int ierr;
627 
628   if (!*rstr || --(*rstr)->refcount > 0)
629     return 0;
630   if ((*rstr)->Destroy) {
631     ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr);
632   }
633   ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr);
634   ierr = CeedFree(rstr); CeedChk(ierr);
635   return 0;
636 }
637 
638 /// @}
639