xref: /libCEED/interface/ceed-elemrestriction.c (revision b7c9bbdafc9b91976b65f80ebb2c5357c2efd8bc)
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 
17ec3da8bcSJed Brown #include <ceed/ceed.h>
18ec3da8bcSJed Brown #include <ceed/backend.h>
193d576824SJeremy L Thompson #include <ceed-impl.h>
203d576824SJeremy L Thompson #include <stdbool.h>
213d576824SJeremy L Thompson #include <stdio.h>
22d7b241e6Sjeremylt 
237a982d89SJeremy L. Thompson /// @file
247a982d89SJeremy L. Thompson /// Implementation of CeedElemRestriction interfaces
257a982d89SJeremy L. Thompson 
267a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
277a982d89SJeremy L. Thompson /// CeedElemRestriction Library Internal Functions
287a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
297a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionDeveloper
307a982d89SJeremy L. Thompson /// @{
317a982d89SJeremy L. Thompson 
327a982d89SJeremy L. Thompson /**
33d979a051Sjeremylt   @brief Permute and pad offsets for a blocked restriction
347a982d89SJeremy L. Thompson 
35d1d35e2fSjeremylt   @param offsets     Array of shape [@a num_elem, @a elem_size]. Row i holds the
36d979a051Sjeremylt                        ordered list of the offsets (into the input CeedVector)
377a982d89SJeremy L. Thompson                        for the unknowns corresponding to element i, where
38d1d35e2fSjeremylt                        0 <= i < @a num_elem. All offsets must be in the range
39d1d35e2fSjeremylt                        [0, @a l_size - 1].
40d1d35e2fSjeremylt   @param blk_offsets Array of permuted and padded offsets of
41d1d35e2fSjeremylt                        shape [@a num_blk, @a elem_size, @a blk_size].
42d1d35e2fSjeremylt   @param num_blk     Number of blocks
43d1d35e2fSjeremylt   @param num_elem    Number of elements
44d1d35e2fSjeremylt   @param blk_size    Number of elements in a block
45d1d35e2fSjeremylt   @param elem_size   Size of each element
467a982d89SJeremy L. Thompson 
477a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
487a982d89SJeremy L. Thompson 
497a982d89SJeremy L. Thompson   @ref Utility
507a982d89SJeremy L. Thompson **/
51d1d35e2fSjeremylt int CeedPermutePadOffsets(const CeedInt *offsets, CeedInt *blk_offsets,
52d1d35e2fSjeremylt                           CeedInt num_blk, CeedInt num_elem, CeedInt blk_size,
53d1d35e2fSjeremylt                           CeedInt elem_size) {
54d1d35e2fSjeremylt   for (CeedInt e=0; e<num_blk*blk_size; e+=blk_size)
55d1d35e2fSjeremylt     for (int j=0; j<blk_size; j++)
56d1d35e2fSjeremylt       for (int k=0; k<elem_size; k++)
57d1d35e2fSjeremylt         blk_offsets[e*elem_size + k*blk_size + j]
58d1d35e2fSjeremylt           = offsets[CeedIntMin(e+j,num_elem-1)*elem_size + k];
59e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
607a982d89SJeremy L. Thompson }
617a982d89SJeremy L. Thompson 
627a982d89SJeremy L. Thompson /// @}
637a982d89SJeremy L. Thompson 
647a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
657a982d89SJeremy L. Thompson /// CeedElemRestriction Backend API
667a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
677a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionBackend
687a982d89SJeremy L. Thompson /// @{
697a982d89SJeremy L. Thompson 
707a982d89SJeremy L. Thompson /**
71a681ae63Sjeremylt 
72a681ae63Sjeremylt   @brief Get the strides of a strided CeedElemRestriction
737a982d89SJeremy L. Thompson 
747a982d89SJeremy L. Thompson   @param rstr          CeedElemRestriction
75a681ae63Sjeremylt   @param[out] strides  Variable to store strides array
767a982d89SJeremy L. Thompson 
777a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
787a982d89SJeremy L. Thompson 
797a982d89SJeremy L. Thompson   @ref Backend
807a982d89SJeremy L. Thompson **/
81a681ae63Sjeremylt int CeedElemRestrictionGetStrides(CeedElemRestriction rstr,
82a681ae63Sjeremylt                                   CeedInt (*strides)[3]) {
83a681ae63Sjeremylt   if (!rstr->strides)
84a681ae63Sjeremylt     // LCOV_EXCL_START
85e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_MINOR,
86e15f9bd0SJeremy L Thompson                      "ElemRestriction has no stride data");
87a681ae63Sjeremylt   // LCOV_EXCL_STOP
88a681ae63Sjeremylt 
89a681ae63Sjeremylt   for (int i=0; i<3; i++)
90a681ae63Sjeremylt     (*strides)[i] = rstr->strides[i];
91e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
927a982d89SJeremy L. Thompson }
937a982d89SJeremy L. Thompson 
947a982d89SJeremy L. Thompson /**
95bd33150aSjeremylt   @brief Get read-only access to a CeedElemRestriction offsets array by memtype
96bd33150aSjeremylt 
97bd33150aSjeremylt   @param rstr          CeedElemRestriction to retrieve offsets
98d1d35e2fSjeremylt   @param mem_type      Memory type on which to access the array.  If the backend
99bd33150aSjeremylt                          uses a different memory type, this will perform a copy
100bd33150aSjeremylt                          (possibly cached).
101d1d35e2fSjeremylt   @param[out] offsets  Array on memory type mem_type
102bd33150aSjeremylt 
103bd33150aSjeremylt   @return An error code: 0 - success, otherwise - failure
104bd33150aSjeremylt 
105bd33150aSjeremylt   @ref User
106bd33150aSjeremylt **/
107d1d35e2fSjeremylt int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr,
108d1d35e2fSjeremylt                                   CeedMemType mem_type,
109bd33150aSjeremylt                                   const CeedInt **offsets) {
110bd33150aSjeremylt   int ierr;
111bd33150aSjeremylt 
112bd33150aSjeremylt   if (!rstr->GetOffsets)
113bd33150aSjeremylt     // LCOV_EXCL_START
114e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_UNSUPPORTED,
115e15f9bd0SJeremy L Thompson                      "Backend does not support GetOffsets");
116bd33150aSjeremylt   // LCOV_EXCL_STOP
117bd33150aSjeremylt 
118d1d35e2fSjeremylt   ierr = rstr->GetOffsets(rstr, mem_type, offsets); CeedChk(ierr);
119d1d35e2fSjeremylt   rstr->num_readers++;
120e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
121430758c8SJeremy L Thompson }
122430758c8SJeremy L Thompson 
123430758c8SJeremy L Thompson /**
124430758c8SJeremy L Thompson   @brief Restore an offsets array obtained using CeedElemRestrictionGetOffsets()
125430758c8SJeremy L Thompson 
126430758c8SJeremy L Thompson   @param rstr     CeedElemRestriction to restore
127430758c8SJeremy L Thompson   @param offsets  Array of offset data
128430758c8SJeremy L Thompson 
129430758c8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
130430758c8SJeremy L Thompson 
131430758c8SJeremy L Thompson   @ref User
132430758c8SJeremy L Thompson **/
133430758c8SJeremy L Thompson int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr,
134430758c8SJeremy L Thompson                                       const CeedInt **offsets) {
135430758c8SJeremy L Thompson   *offsets = NULL;
136d1d35e2fSjeremylt   rstr->num_readers--;
137e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
138bd33150aSjeremylt }
139bd33150aSjeremylt 
140bd33150aSjeremylt /**
1413ac43b2cSJeremy L Thompson   @brief Get the strided status of a CeedElemRestriction
1423ac43b2cSJeremy L Thompson 
1433ac43b2cSJeremy L Thompson   @param rstr             CeedElemRestriction
144d1d35e2fSjeremylt   @param[out] is_strided  Variable to store strided status, 1 if strided else 0
1453ac43b2cSJeremy L Thompson 
1463ac43b2cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1473ac43b2cSJeremy L Thompson 
1483ac43b2cSJeremy L Thompson   @ref Backend
1493ac43b2cSJeremy L Thompson **/
150d1d35e2fSjeremylt int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) {
151d1d35e2fSjeremylt   *is_strided = rstr->strides ? true : false;
152e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1533ac43b2cSJeremy L Thompson }
1543ac43b2cSJeremy L Thompson 
1553ac43b2cSJeremy L Thompson /**
156a681ae63Sjeremylt   @brief Get the backend stride status of a CeedElemRestriction
1577a982d89SJeremy L. Thompson 
1587a982d89SJeremy L. Thompson   @param rstr                      CeedElemRestriction
15996b902e2Sjeremylt   @param[out] has_backend_strides  Variable to store stride status
1607a982d89SJeremy L. Thompson 
1617a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1627a982d89SJeremy L. Thompson 
1637a982d89SJeremy L. Thompson   @ref Backend
1647a982d89SJeremy L. Thompson **/
165fd364f38SJeremy L Thompson int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr,
166d1d35e2fSjeremylt     bool *has_backend_strides) {
167a681ae63Sjeremylt   if (!rstr->strides)
168a681ae63Sjeremylt     // LCOV_EXCL_START
169e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_MINOR,
170e15f9bd0SJeremy L Thompson                      "ElemRestriction has no stride data");
171a681ae63Sjeremylt   // LCOV_EXCL_STOP
1727a982d89SJeremy L. Thompson 
173d1d35e2fSjeremylt   *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) &&
174a681ae63Sjeremylt                           (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
175a681ae63Sjeremylt                           (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
176e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1777a982d89SJeremy L. Thompson }
1787a982d89SJeremy L. Thompson 
1797a982d89SJeremy L. Thompson /**
18049fd234cSJeremy L Thompson 
18149fd234cSJeremy L Thompson   @brief Get the E-vector layout of a CeedElemRestriction
18249fd234cSJeremy L Thompson 
18349fd234cSJeremy L Thompson   @param rstr         CeedElemRestriction
18449fd234cSJeremy L Thompson   @param[out] layout  Variable to store layout array,
18549fd234cSJeremy L Thompson                         stored as [nodes, components, elements].
18649fd234cSJeremy L Thompson                         The data for node i, component j, element k in the
18749fd234cSJeremy L Thompson                         E-vector is given by
18895e93d34SJeremy L Thompson                         i*layout[0] + j*layout[1] + k*layout[2]
18949fd234cSJeremy L Thompson 
19049fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
19149fd234cSJeremy L Thompson 
19249fd234cSJeremy L Thompson   @ref Backend
19349fd234cSJeremy L Thompson **/
19449fd234cSJeremy L Thompson int CeedElemRestrictionGetELayout(CeedElemRestriction rstr,
19549fd234cSJeremy L Thompson                                   CeedInt (*layout)[3]) {
19649fd234cSJeremy L Thompson   if (!rstr->layout[0])
19749fd234cSJeremy L Thompson     // LCOV_EXCL_START
198e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_MINOR,
199e15f9bd0SJeremy L Thompson                      "ElemRestriction has no layout data");
20049fd234cSJeremy L Thompson   // LCOV_EXCL_STOP
20149fd234cSJeremy L Thompson 
20249fd234cSJeremy L Thompson   for (int i=0; i<3; i++)
20349fd234cSJeremy L Thompson     (*layout)[i] = rstr->layout[i];
204e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
20549fd234cSJeremy L Thompson }
20649fd234cSJeremy L Thompson 
20749fd234cSJeremy L Thompson /**
20849fd234cSJeremy L Thompson 
20949fd234cSJeremy L Thompson   @brief Set the E-vector layout of a CeedElemRestriction
21049fd234cSJeremy L Thompson 
21149fd234cSJeremy L Thompson   @param rstr    CeedElemRestriction
21249fd234cSJeremy L Thompson   @param layout  Variable to containing layout array,
21349fd234cSJeremy L Thompson                    stored as [nodes, components, elements].
21449fd234cSJeremy L Thompson                    The data for node i, component j, element k in the
21549fd234cSJeremy L Thompson                    E-vector is given by
21695e93d34SJeremy L Thompson                    i*layout[0] + j*layout[1] + k*layout[2]
21749fd234cSJeremy L Thompson 
21849fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
21949fd234cSJeremy L Thompson 
22049fd234cSJeremy L Thompson   @ref Backend
22149fd234cSJeremy L Thompson **/
22249fd234cSJeremy L Thompson int CeedElemRestrictionSetELayout(CeedElemRestriction rstr,
22349fd234cSJeremy L Thompson                                   CeedInt layout[3]) {
22449fd234cSJeremy L Thompson   for (int i = 0; i<3; i++)
22549fd234cSJeremy L Thompson     rstr->layout[i] = layout[i];
226e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
22749fd234cSJeremy L Thompson }
22849fd234cSJeremy L Thompson 
22949fd234cSJeremy L Thompson /**
2307a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedElemRestriction
2317a982d89SJeremy L. Thompson 
2327a982d89SJeremy L. Thompson   @param rstr       CeedElemRestriction
2337a982d89SJeremy L. Thompson   @param[out] data  Variable to store data
2347a982d89SJeremy L. Thompson 
2357a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2367a982d89SJeremy L. Thompson 
2377a982d89SJeremy L. Thompson   @ref Backend
2387a982d89SJeremy L. Thompson **/
239777ff853SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) {
240777ff853SJeremy L Thompson   *(void **)data = rstr->data;
241e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2427a982d89SJeremy L. Thompson }
2437a982d89SJeremy L. Thompson 
2447a982d89SJeremy L. Thompson /**
2457a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedElemRestriction
2467a982d89SJeremy L. Thompson 
2477a982d89SJeremy L. Thompson   @param[out] rstr  CeedElemRestriction
2487a982d89SJeremy L. Thompson   @param data       Data to set
2497a982d89SJeremy L. Thompson 
2507a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2517a982d89SJeremy L. Thompson 
2527a982d89SJeremy L. Thompson   @ref Backend
2537a982d89SJeremy L. Thompson **/
254777ff853SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) {
255777ff853SJeremy L Thompson   rstr->data = data;
256e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2577a982d89SJeremy L. Thompson }
2587a982d89SJeremy L. Thompson 
25934359f16Sjeremylt /**
26034359f16Sjeremylt   @brief Increment the reference counter for a CeedElemRestriction
26134359f16Sjeremylt 
26234359f16Sjeremylt   @param rstr  ElemRestriction to increment the reference counter
26334359f16Sjeremylt 
26434359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
26534359f16Sjeremylt 
26634359f16Sjeremylt   @ref Backend
26734359f16Sjeremylt **/
2689560d06aSjeremylt int CeedElemRestrictionReference(CeedElemRestriction rstr) {
26934359f16Sjeremylt   rstr->ref_count++;
27034359f16Sjeremylt   return CEED_ERROR_SUCCESS;
27134359f16Sjeremylt }
27234359f16Sjeremylt 
2737a982d89SJeremy L. Thompson /// @}
2747a982d89SJeremy L. Thompson 
27515910d16Sjeremylt /// @cond DOXYGEN_SKIP
27615910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
27715910d16Sjeremylt /// @endcond
27815910d16Sjeremylt 
2797a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
2807a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
2817a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
2827a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
283d7b241e6Sjeremylt /// @{
284d7b241e6Sjeremylt 
2857a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
28645f1e315Sjeremylt const CeedInt CEED_STRIDES_BACKEND[3] = {0};
2877a982d89SJeremy L. Thompson 
2884cc79fe7SJed Brown /// Indicate that no CeedElemRestriction is provided by the user
2897a982d89SJeremy L. Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE =
2907a982d89SJeremy L. Thompson   &ceed_elemrestriction_none;
2917a982d89SJeremy L. Thompson 
292d7b241e6Sjeremylt /**
293b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
294d7b241e6Sjeremylt 
295b11c1e72Sjeremylt   @param ceed         A Ceed object where the CeedElemRestriction will be created
296d1d35e2fSjeremylt   @param num_elem     Number of elements described in the @a offsets array
297d1d35e2fSjeremylt   @param elem_size    Size (number of "nodes") per element
298d1d35e2fSjeremylt   @param num_comp     Number of field components per interpolation node
29995bb1877Svaleriabarra                         (1 for scalar fields)
300d1d35e2fSjeremylt   @param comp_stride  Stride between components for the same L-vector "node".
30195e93d34SJeremy L Thompson                         Data for node i, component j, element k can be found in
30295e93d34SJeremy L Thompson                         the L-vector at index
303d1d35e2fSjeremylt                         offsets[i + k*elem_size] + j*comp_stride.
304d1d35e2fSjeremylt   @param l_size       The size of the L-vector. This vector may be larger than
305d979a051Sjeremylt                         the elements and fields given by this restriction.
306d1d35e2fSjeremylt   @param mem_type     Memory type of the @a offsets array, see CeedMemType
307d1d35e2fSjeremylt   @param copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
308d1d35e2fSjeremylt   @param offsets      Array of shape [@a num_elem, @a elem_size]. Row i holds the
309d979a051Sjeremylt                         ordered list of the offsets (into the input CeedVector)
3108795c945Sjeremylt                         for the unknowns corresponding to element i, where
311d1d35e2fSjeremylt                         0 <= i < @a num_elem. All offsets must be in the range
312d1d35e2fSjeremylt                         [0, @a l_size - 1].
3134ce2993fSjeremylt   @param[out] rstr    Address of the variable where the newly created
314b11c1e72Sjeremylt                         CeedElemRestriction will be stored
315d7b241e6Sjeremylt 
316b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
317dfdf5a53Sjeremylt 
3187a982d89SJeremy L. Thompson   @ref User
319b11c1e72Sjeremylt **/
320d1d35e2fSjeremylt int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size,
321d1d35e2fSjeremylt                               CeedInt num_comp, CeedInt comp_stride,
322d1d35e2fSjeremylt                               CeedInt l_size, CeedMemType mem_type,
323d1d35e2fSjeremylt                               CeedCopyMode copy_mode, const CeedInt *offsets,
3244ce2993fSjeremylt                               CeedElemRestriction *rstr) {
325d7b241e6Sjeremylt   int ierr;
326d7b241e6Sjeremylt 
3275fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
3285fe0d4faSjeremylt     Ceed delegate;
329aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
330aefd8378Sjeremylt     CeedChk(ierr);
3315fe0d4faSjeremylt 
3325fe0d4faSjeremylt     if (!delegate)
333c042f62fSJeremy L Thompson       // LCOV_EXCL_START
334e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
335e15f9bd0SJeremy L Thompson                        "Backend does not support ElemRestrictionCreate");
336c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
3375fe0d4faSjeremylt 
338d1d35e2fSjeremylt     ierr = CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp,
339d1d35e2fSjeremylt                                      comp_stride, l_size, mem_type, copy_mode,
340d979a051Sjeremylt                                      offsets, rstr); CeedChk(ierr);
341e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
3425fe0d4faSjeremylt   }
3435fe0d4faSjeremylt 
3444ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
3454ce2993fSjeremylt   (*rstr)->ceed = ceed;
3469560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
347d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
348d1d35e2fSjeremylt   (*rstr)->num_elem = num_elem;
349d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
350d1d35e2fSjeremylt   (*rstr)->num_comp = num_comp;
351d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
352d1d35e2fSjeremylt   (*rstr)->l_size = l_size;
353d1d35e2fSjeremylt   (*rstr)->num_blk = num_elem;
354d1d35e2fSjeremylt   (*rstr)->blk_size = 1;
355d1d35e2fSjeremylt   ierr = ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, *rstr);
356d979a051Sjeremylt   CeedChk(ierr);
357e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
358d7b241e6Sjeremylt }
359d7b241e6Sjeremylt 
360d7b241e6Sjeremylt /**
3617509a596Sjeremylt   @brief Create a strided CeedElemRestriction
362d7b241e6Sjeremylt 
363b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
364d1d35e2fSjeremylt   @param num_elem   Number of elements described by the restriction
365d1d35e2fSjeremylt   @param elem_size  Size (number of "nodes") per element
366d1d35e2fSjeremylt   @param num_comp   Number of field components per interpolation "node"
36795bb1877Svaleriabarra                       (1 for scalar fields)
368d1d35e2fSjeremylt   @param l_size     The size of the L-vector. This vector may be larger than
369d979a051Sjeremylt                       the elements and fields given by this restriction.
3707509a596Sjeremylt   @param strides    Array for strides between [nodes, components, elements].
37195e93d34SJeremy L Thompson                       Data for node i, component j, element k can be found in
37295e93d34SJeremy L Thompson                       the L-vector at index
37395e93d34SJeremy L Thompson                       i*strides[0] + j*strides[1] + k*strides[2].
37495e93d34SJeremy L Thompson                       @a CEED_STRIDES_BACKEND may be used with vectors created
37595e93d34SJeremy L Thompson                       by a Ceed backend.
3764ce2993fSjeremylt   @param rstr       Address of the variable where the newly created
377b11c1e72Sjeremylt                       CeedElemRestriction will be stored
378d7b241e6Sjeremylt 
379b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
380dfdf5a53Sjeremylt 
3817a982d89SJeremy L. Thompson   @ref User
382b11c1e72Sjeremylt **/
383d1d35e2fSjeremylt int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem,
384d1d35e2fSjeremylt                                      CeedInt elem_size,
385d1d35e2fSjeremylt                                      CeedInt num_comp, CeedInt l_size,
3868621c6c6SJeremy L Thompson                                      const CeedInt strides[3],
387f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
388d7b241e6Sjeremylt   int ierr;
389d7b241e6Sjeremylt 
3905fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
3915fe0d4faSjeremylt     Ceed delegate;
392aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
393aefd8378Sjeremylt     CeedChk(ierr);
3945fe0d4faSjeremylt 
3955fe0d4faSjeremylt     if (!delegate)
396c042f62fSJeremy L Thompson       // LCOV_EXCL_START
397e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
398e15f9bd0SJeremy L Thompson                        "Backend does not support ElemRestrictionCreate");
399c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
4005fe0d4faSjeremylt 
401d1d35e2fSjeremylt     ierr = CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp,
402d1d35e2fSjeremylt                                             l_size, strides, rstr);
403d979a051Sjeremylt     CeedChk(ierr);
404e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
4055fe0d4faSjeremylt   }
4065fe0d4faSjeremylt 
4074ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
4084ce2993fSjeremylt   (*rstr)->ceed = ceed;
4099560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
410d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
411d1d35e2fSjeremylt   (*rstr)->num_elem = num_elem;
412d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
413d1d35e2fSjeremylt   (*rstr)->num_comp = num_comp;
414d1d35e2fSjeremylt   (*rstr)->l_size = l_size;
415d1d35e2fSjeremylt   (*rstr)->num_blk = num_elem;
416d1d35e2fSjeremylt   (*rstr)->blk_size = 1;
4177509a596Sjeremylt   ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr);
4187509a596Sjeremylt   for (int i=0; i<3; i++)
4197509a596Sjeremylt     (*rstr)->strides[i] = strides[i];
4201dfeef1dSjeremylt   ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL,
4211dfeef1dSjeremylt                                      *rstr);
4224b8bea3bSJed Brown   CeedChk(ierr);
423e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
424d7b241e6Sjeremylt }
425d7b241e6Sjeremylt 
426d7b241e6Sjeremylt /**
427b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
428d7b241e6Sjeremylt 
429d7b241e6Sjeremylt   @param ceed         A Ceed object where the CeedElemRestriction will be created.
430d1d35e2fSjeremylt   @param num_elem     Number of elements described in the @a offsets array.
431d1d35e2fSjeremylt   @param elem_size    Size (number of unknowns) per element
432d1d35e2fSjeremylt   @param blk_size     Number of elements in a block
433d1d35e2fSjeremylt   @param num_comp     Number of field components per interpolation node
43495bb1877Svaleriabarra                         (1 for scalar fields)
435d1d35e2fSjeremylt   @param comp_stride  Stride between components for the same L-vector "node".
43695e93d34SJeremy L Thompson                         Data for node i, component j, element k can be found in
43795e93d34SJeremy L Thompson                         the L-vector at index
438d1d35e2fSjeremylt                         offsets[i + k*elem_size] + j*comp_stride.
439d1d35e2fSjeremylt   @param l_size       The size of the L-vector. This vector may be larger than
440d979a051Sjeremylt                         the elements and fields given by this restriction.
441d1d35e2fSjeremylt   @param mem_type     Memory type of the @a offsets array, see CeedMemType
442d1d35e2fSjeremylt   @param copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
443d1d35e2fSjeremylt   @param offsets      Array of shape [@a num_elem, @a elem_size]. Row i holds the
444d979a051Sjeremylt                         ordered list of the offsets (into the input CeedVector)
4458795c945Sjeremylt                         for the unknowns corresponding to element i, where
446d1d35e2fSjeremylt                         0 <= i < @a num_elem. All offsets must be in the range
447d1d35e2fSjeremylt                         [0, @a l_size - 1]. The backend will permute and pad this
4488795c945Sjeremylt                         array to the desired ordering for the blocksize, which is
4498795c945Sjeremylt                         typically given by the backend. The default reordering is
4508795c945Sjeremylt                         to interlace elements.
4514ce2993fSjeremylt   @param rstr         Address of the variable where the newly created
452b11c1e72Sjeremylt                         CeedElemRestriction will be stored
453d7b241e6Sjeremylt 
454b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
455dfdf5a53Sjeremylt 
4567a982d89SJeremy L. Thompson   @ref Backend
457b11c1e72Sjeremylt  **/
458d1d35e2fSjeremylt int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem,
459d1d35e2fSjeremylt                                      CeedInt elem_size,
460d1d35e2fSjeremylt                                      CeedInt blk_size, CeedInt num_comp,
461d1d35e2fSjeremylt                                      CeedInt comp_stride, CeedInt l_size,
462d1d35e2fSjeremylt                                      CeedMemType mem_type, CeedCopyMode copy_mode,
463d979a051Sjeremylt                                      const CeedInt *offsets,
4644ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
465d7b241e6Sjeremylt   int ierr;
466d1d35e2fSjeremylt   CeedInt *blk_offsets;
467d1d35e2fSjeremylt   CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
468d7b241e6Sjeremylt 
4695fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
4705fe0d4faSjeremylt     Ceed delegate;
471aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
472aefd8378Sjeremylt     CeedChk(ierr);
4735fe0d4faSjeremylt 
4745fe0d4faSjeremylt     if (!delegate)
475c042f62fSJeremy L Thompson       // LCOV_EXCL_START
476e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support "
4771d102b48SJeremy L Thompson                        "ElemRestrictionCreateBlocked");
478c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
4795fe0d4faSjeremylt 
480d1d35e2fSjeremylt     ierr = CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, blk_size,
481d1d35e2fSjeremylt                                             num_comp, comp_stride, l_size, mem_type,
482d1d35e2fSjeremylt                                             copy_mode, offsets, rstr);
483d979a051Sjeremylt     CeedChk(ierr);
484e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
4855fe0d4faSjeremylt   }
486d7b241e6Sjeremylt 
4874ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
488d7b241e6Sjeremylt 
489d1d35e2fSjeremylt   ierr = CeedCalloc(num_blk*blk_size*elem_size, &blk_offsets); CeedChk(ierr);
490d1d35e2fSjeremylt   ierr = CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size,
491d1d35e2fSjeremylt                                elem_size); CeedChk(ierr);
492d7b241e6Sjeremylt 
4934ce2993fSjeremylt   (*rstr)->ceed = ceed;
4949560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
495d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
496d1d35e2fSjeremylt   (*rstr)->num_elem = num_elem;
497d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
498d1d35e2fSjeremylt   (*rstr)->num_comp = num_comp;
499d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
500d1d35e2fSjeremylt   (*rstr)->l_size = l_size;
501d1d35e2fSjeremylt   (*rstr)->num_blk = num_blk;
502d1d35e2fSjeremylt   (*rstr)->blk_size = blk_size;
503667bc5fcSjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
504d1d35e2fSjeremylt          (const CeedInt *) blk_offsets, *rstr); CeedChk(ierr);
505d1d35e2fSjeremylt   if (copy_mode == CEED_OWN_POINTER) {
506d979a051Sjeremylt     ierr = CeedFree(&offsets); CeedChk(ierr);
5071d102b48SJeremy L Thompson   }
508e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
509d7b241e6Sjeremylt }
510d7b241e6Sjeremylt 
511b11c1e72Sjeremylt /**
5127509a596Sjeremylt   @brief Create a blocked strided CeedElemRestriction
5137509a596Sjeremylt 
5147509a596Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
515d1d35e2fSjeremylt   @param num_elem   Number of elements described by the restriction
516d1d35e2fSjeremylt   @param elem_size  Size (number of "nodes") per element
517d1d35e2fSjeremylt   @param blk_size   Number of elements in a block
518d1d35e2fSjeremylt   @param num_comp   Number of field components per interpolation node
5197509a596Sjeremylt                       (1 for scalar fields)
520d1d35e2fSjeremylt   @param l_size     The size of the L-vector. This vector may be larger than
521d979a051Sjeremylt                       the elements and fields given by this restriction.
5227509a596Sjeremylt   @param strides    Array for strides between [nodes, components, elements].
52395e93d34SJeremy L Thompson                       Data for node i, component j, element k can be found in
52495e93d34SJeremy L Thompson                       the L-vector at index
52595e93d34SJeremy L Thompson                       i*strides[0] + j*strides[1] + k*strides[2].
52695e93d34SJeremy L Thompson                       @a CEED_STRIDES_BACKEND may be used with vectors created
52795e93d34SJeremy L Thompson                       by a Ceed backend.
5287509a596Sjeremylt   @param rstr       Address of the variable where the newly created
5297509a596Sjeremylt                       CeedElemRestriction will be stored
5307509a596Sjeremylt 
5317509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
5327509a596Sjeremylt 
5337a982d89SJeremy L. Thompson   @ref User
5347509a596Sjeremylt **/
535d1d35e2fSjeremylt int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem,
536d1d35e2fSjeremylt     CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedInt l_size,
5378621c6c6SJeremy L Thompson     const CeedInt strides[3], CeedElemRestriction *rstr) {
5387509a596Sjeremylt   int ierr;
539d1d35e2fSjeremylt   CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
5407509a596Sjeremylt 
5417509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
5427509a596Sjeremylt     Ceed delegate;
5437509a596Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
5447509a596Sjeremylt     CeedChk(ierr);
5457509a596Sjeremylt 
5467509a596Sjeremylt     if (!delegate)
5477509a596Sjeremylt       // LCOV_EXCL_START
548e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support "
5497509a596Sjeremylt                        "ElemRestrictionCreateBlocked");
5507509a596Sjeremylt     // LCOV_EXCL_STOP
5517509a596Sjeremylt 
552d1d35e2fSjeremylt     ierr = CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size,
553d1d35e2fSjeremylt            blk_size, num_comp, l_size, strides, rstr); CeedChk(ierr);
554e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
5557509a596Sjeremylt   }
5567509a596Sjeremylt 
5577509a596Sjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
5587509a596Sjeremylt 
5597509a596Sjeremylt   (*rstr)->ceed = ceed;
5609560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
561d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
562d1d35e2fSjeremylt   (*rstr)->num_elem = num_elem;
563d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
564d1d35e2fSjeremylt   (*rstr)->num_comp = num_comp;
565d1d35e2fSjeremylt   (*rstr)->l_size = l_size;
566d1d35e2fSjeremylt   (*rstr)->num_blk = num_blk;
567d1d35e2fSjeremylt   (*rstr)->blk_size = blk_size;
5687509a596Sjeremylt   ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr);
5697509a596Sjeremylt   for (int i=0; i<3; i++)
5707509a596Sjeremylt     (*rstr)->strides[i] = strides[i];
5717509a596Sjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
5727509a596Sjeremylt          NULL, *rstr); CeedChk(ierr);
573e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5747509a596Sjeremylt }
5757509a596Sjeremylt 
5767509a596Sjeremylt /**
5779560d06aSjeremylt   @brief Copy the pointer to a CeedElemRestriction. Both pointers should
5789560d06aSjeremylt            be destroyed with `CeedElemRestrictionDestroy()`;
5799560d06aSjeremylt            Note: If `*rstr_copy` is non-NULL, then it is assumed that
5809560d06aSjeremylt            `*rstr_copy` is a pointer to a CeedElemRestriction. This
5819560d06aSjeremylt            CeedElemRestriction will be destroyed if `*rstr_copy` is the
5829560d06aSjeremylt            only reference to this CeedElemRestriction.
5839560d06aSjeremylt 
5849560d06aSjeremylt   @param rstr            CeedElemRestriction to copy reference to
5859560d06aSjeremylt   @param[out] rstr_copy  Variable to store copied reference
5869560d06aSjeremylt 
5879560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
5889560d06aSjeremylt 
5899560d06aSjeremylt   @ref User
5909560d06aSjeremylt **/
5919560d06aSjeremylt int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr,
5929560d06aSjeremylt                                      CeedElemRestriction *rstr_copy) {
5939560d06aSjeremylt   int ierr;
5949560d06aSjeremylt 
5959560d06aSjeremylt   ierr = CeedElemRestrictionReference(rstr); CeedChk(ierr);
5969560d06aSjeremylt   ierr = CeedElemRestrictionDestroy(rstr_copy); CeedChk(ierr);
5979560d06aSjeremylt   *rstr_copy = rstr;
5989560d06aSjeremylt   return CEED_ERROR_SUCCESS;
5999560d06aSjeremylt }
6009560d06aSjeremylt 
6019560d06aSjeremylt /**
602b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
603b11c1e72Sjeremylt 
6044ce2993fSjeremylt   @param rstr   CeedElemRestriction
605d1d35e2fSjeremylt   @param l_vec  The address of the L-vector to be created, or NULL
606d1d35e2fSjeremylt   @param e_vec  The address of the E-vector to be created, or NULL
607b11c1e72Sjeremylt 
608b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
609dfdf5a53Sjeremylt 
6107a982d89SJeremy L. Thompson   @ref User
611b11c1e72Sjeremylt **/
612d1d35e2fSjeremylt int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec,
613d1d35e2fSjeremylt                                     CeedVector *e_vec) {
614d7b241e6Sjeremylt   int ierr;
615d1d35e2fSjeremylt   CeedInt e_size, l_size;
616d1d35e2fSjeremylt   l_size = rstr->l_size;
617d1d35e2fSjeremylt   e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
618d1d35e2fSjeremylt   if (l_vec) {
619d1d35e2fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, l_size, l_vec); CeedChk(ierr);
620d7b241e6Sjeremylt   }
621d1d35e2fSjeremylt   if (e_vec) {
622d1d35e2fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, e_size, e_vec); CeedChk(ierr);
623d7b241e6Sjeremylt   }
624e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
625d7b241e6Sjeremylt }
626d7b241e6Sjeremylt 
627d7b241e6Sjeremylt /**
628d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
629d7b241e6Sjeremylt 
6304ce2993fSjeremylt   @param rstr    CeedElemRestriction
631d1d35e2fSjeremylt   @param t_mode  Apply restriction or transpose
632d1d35e2fSjeremylt   @param u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
633d1d35e2fSjeremylt   @param ru      Output vector (of shape [@a num_elem * @a elem_size] when
634d1d35e2fSjeremylt                    t_mode=@ref CEED_NOTRANSPOSE). Ordering of the e-vector is decided
6357aaeacdcSjeremylt                    by the backend.
6364cc79fe7SJed Brown   @param request Request or @ref CEED_REQUEST_IMMEDIATE
637b11c1e72Sjeremylt 
638b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
639dfdf5a53Sjeremylt 
6407a982d89SJeremy L. Thompson   @ref User
641b11c1e72Sjeremylt **/
642d1d35e2fSjeremylt int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode,
643a8d32208Sjeremylt                              CeedVector u, CeedVector ru,
644a8d32208Sjeremylt                              CeedRequest *request) {
645d7b241e6Sjeremylt   CeedInt m, n;
646d7b241e6Sjeremylt   int ierr;
647d7b241e6Sjeremylt 
648d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
649d1d35e2fSjeremylt     m = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
650d1d35e2fSjeremylt     n = rstr->l_size;
651d7b241e6Sjeremylt   } else {
652d1d35e2fSjeremylt     m = rstr->l_size;
653d1d35e2fSjeremylt     n = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
654d7b241e6Sjeremylt   }
655d7b241e6Sjeremylt   if (n != u->length)
656c042f62fSJeremy L Thompson     // LCOV_EXCL_START
657e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
658e15f9bd0SJeremy L Thompson                      "Input vector size %d not compatible with "
6591d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
660c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
661a8d32208Sjeremylt   if (m != ru->length)
662c042f62fSJeremy L Thompson     // LCOV_EXCL_START
663e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
664e15f9bd0SJeremy L Thompson                      "Output vector size %d not compatible with "
665a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
666c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
667d1d35e2fSjeremylt   ierr = rstr->Apply(rstr, t_mode, u, ru, request); CeedChk(ierr);
668e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
669d7b241e6Sjeremylt }
670d7b241e6Sjeremylt 
671d7b241e6Sjeremylt /**
672d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
673be9261b7Sjeremylt 
674be9261b7Sjeremylt   @param rstr    CeedElemRestriction
6751f37b403Sjeremylt   @param block   Block number to restrict to/from, i.e. block=0 will handle
676d1d35e2fSjeremylt                    elements [0 : blk_size] and block=3 will handle elements
677d1d35e2fSjeremylt                    [3*blk_size : 4*blk_size]
678d1d35e2fSjeremylt   @param t_mode  Apply restriction or transpose
679d1d35e2fSjeremylt   @param u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
680d1d35e2fSjeremylt   @param ru      Output vector (of shape [@a blk_size * @a elem_size] when
681d1d35e2fSjeremylt                    t_mode=@ref CEED_NOTRANSPOSE). Ordering of the e-vector is decided
6827aaeacdcSjeremylt                    by the backend.
6834cc79fe7SJed Brown   @param request Request or @ref CEED_REQUEST_IMMEDIATE
684be9261b7Sjeremylt 
685be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
686be9261b7Sjeremylt 
6877a982d89SJeremy L. Thompson   @ref Backend
688be9261b7Sjeremylt **/
689be9261b7Sjeremylt int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block,
690d1d35e2fSjeremylt                                   CeedTransposeMode t_mode, CeedVector u,
691a8d32208Sjeremylt                                   CeedVector ru, CeedRequest *request) {
692be9261b7Sjeremylt   CeedInt m, n;
693be9261b7Sjeremylt   int ierr;
694be9261b7Sjeremylt 
695d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
696d1d35e2fSjeremylt     m = rstr->blk_size * rstr->elem_size * rstr->num_comp;
697d1d35e2fSjeremylt     n = rstr->l_size;
698be9261b7Sjeremylt   } else {
699d1d35e2fSjeremylt     m = rstr->l_size;
700d1d35e2fSjeremylt     n = rstr->blk_size * rstr->elem_size * rstr->num_comp;
701be9261b7Sjeremylt   }
702be9261b7Sjeremylt   if (n != u->length)
703c042f62fSJeremy L Thompson     // LCOV_EXCL_START
704e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
705e15f9bd0SJeremy L Thompson                      "Input vector size %d not compatible with "
7061d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
707c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
708a8d32208Sjeremylt   if (m != ru->length)
709c042f62fSJeremy L Thompson     // LCOV_EXCL_START
710e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
711e15f9bd0SJeremy L Thompson                      "Output vector size %d not compatible with "
712a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
713c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
714d1d35e2fSjeremylt   if (rstr->blk_size*block > rstr->num_elem)
715c042f62fSJeremy L Thompson     // LCOV_EXCL_START
716e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
717e15f9bd0SJeremy L Thompson                      "Cannot retrieve block %d, element %d > "
718d1d35e2fSjeremylt                      "total elements %d", block, rstr->blk_size*block,
719d1d35e2fSjeremylt                      rstr->num_elem);
720c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
721d1d35e2fSjeremylt   ierr = rstr->ApplyBlock(rstr, block, t_mode, u, ru, request);
722be9261b7Sjeremylt   CeedChk(ierr);
723e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
724be9261b7Sjeremylt }
725be9261b7Sjeremylt 
726be9261b7Sjeremylt /**
727*b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedElemRestriction
728*b7c9bbdaSJeremy L Thompson 
729*b7c9bbdaSJeremy L Thompson   @param rstr       CeedElemRestriction
730*b7c9bbdaSJeremy L Thompson   @param[out] ceed  Variable to store Ceed
731*b7c9bbdaSJeremy L Thompson 
732*b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
733*b7c9bbdaSJeremy L Thompson 
734*b7c9bbdaSJeremy L Thompson   @ref Advanced
735*b7c9bbdaSJeremy L Thompson **/
736*b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
737*b7c9bbdaSJeremy L Thompson   *ceed = rstr->ceed;
738*b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
739*b7c9bbdaSJeremy L Thompson }
740*b7c9bbdaSJeremy L Thompson 
741*b7c9bbdaSJeremy L Thompson /**
742d979a051Sjeremylt   @brief Get the L-vector component stride
743a681ae63Sjeremylt 
744a681ae63Sjeremylt   @param rstr              CeedElemRestriction
745d1d35e2fSjeremylt   @param[out] comp_stride  Variable to store component stride
746a681ae63Sjeremylt 
747a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
748a681ae63Sjeremylt 
749*b7c9bbdaSJeremy L Thompson   @ref Advanced
750a681ae63Sjeremylt **/
751d979a051Sjeremylt int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr,
752d1d35e2fSjeremylt                                      CeedInt *comp_stride) {
753d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
754e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
755a681ae63Sjeremylt }
756a681ae63Sjeremylt 
757a681ae63Sjeremylt /**
758a681ae63Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
759a681ae63Sjeremylt 
760a681ae63Sjeremylt   @param rstr           CeedElemRestriction
761d1d35e2fSjeremylt   @param[out] num_elem  Variable to store number of elements
762a681ae63Sjeremylt 
763a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
764a681ae63Sjeremylt 
765*b7c9bbdaSJeremy L Thompson   @ref Advanced
766a681ae63Sjeremylt **/
767a681ae63Sjeremylt int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
768d1d35e2fSjeremylt                                       CeedInt *num_elem) {
769d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
770e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
771a681ae63Sjeremylt }
772a681ae63Sjeremylt 
773a681ae63Sjeremylt /**
774a681ae63Sjeremylt   @brief Get the size of elements in the CeedElemRestriction
775a681ae63Sjeremylt 
776a681ae63Sjeremylt   @param rstr            CeedElemRestriction
777d1d35e2fSjeremylt   @param[out] elem_size  Variable to store size of elements
778a681ae63Sjeremylt 
779a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
780a681ae63Sjeremylt 
781*b7c9bbdaSJeremy L Thompson   @ref Advanced
782a681ae63Sjeremylt **/
783a681ae63Sjeremylt int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
784d1d35e2fSjeremylt                                       CeedInt *elem_size) {
785d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
786e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
787a681ae63Sjeremylt }
788a681ae63Sjeremylt 
789a681ae63Sjeremylt /**
790d979a051Sjeremylt   @brief Get the size of the l-vector for a CeedElemRestriction
791a681ae63Sjeremylt 
792a681ae63Sjeremylt   @param rstr         CeedElemRestriction
793d1d35e2fSjeremylt   @param[out] l_size  Variable to store number of nodes
794a681ae63Sjeremylt 
795a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
796a681ae63Sjeremylt 
797*b7c9bbdaSJeremy L Thompson   @ref Advanced
798a681ae63Sjeremylt **/
799d979a051Sjeremylt int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr,
800d1d35e2fSjeremylt                                       CeedInt *l_size) {
801d1d35e2fSjeremylt   *l_size = rstr->l_size;
802e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
803a681ae63Sjeremylt }
804a681ae63Sjeremylt 
805a681ae63Sjeremylt /**
806a681ae63Sjeremylt   @brief Get the number of components in the elements of a
807a681ae63Sjeremylt          CeedElemRestriction
808a681ae63Sjeremylt 
809a681ae63Sjeremylt   @param rstr           CeedElemRestriction
810d1d35e2fSjeremylt   @param[out] num_comp  Variable to store number of components
811a681ae63Sjeremylt 
812a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
813a681ae63Sjeremylt 
814*b7c9bbdaSJeremy L Thompson   @ref Advanced
815a681ae63Sjeremylt **/
816a681ae63Sjeremylt int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
817d1d35e2fSjeremylt                                         CeedInt *num_comp) {
818d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
819e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
820a681ae63Sjeremylt }
821a681ae63Sjeremylt 
822a681ae63Sjeremylt /**
823a681ae63Sjeremylt   @brief Get the number of blocks in a CeedElemRestriction
824a681ae63Sjeremylt 
825a681ae63Sjeremylt   @param rstr            CeedElemRestriction
826d1d35e2fSjeremylt   @param[out] num_block  Variable to store number of blocks
827a681ae63Sjeremylt 
828a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
829a681ae63Sjeremylt 
830*b7c9bbdaSJeremy L Thompson   @ref Advanced
831a681ae63Sjeremylt **/
832a681ae63Sjeremylt int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
833d1d35e2fSjeremylt                                     CeedInt *num_block) {
834d1d35e2fSjeremylt   *num_block = rstr->num_blk;
835e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
836a681ae63Sjeremylt }
837a681ae63Sjeremylt 
838a681ae63Sjeremylt /**
839a681ae63Sjeremylt   @brief Get the size of blocks in the CeedElemRestriction
840a681ae63Sjeremylt 
841a681ae63Sjeremylt   @param rstr           CeedElemRestriction
842d1d35e2fSjeremylt   @param[out] blk_size  Variable to store size of blocks
843a681ae63Sjeremylt 
844a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
845a681ae63Sjeremylt 
846*b7c9bbdaSJeremy L Thompson   @ref Advanced
847a681ae63Sjeremylt **/
848a681ae63Sjeremylt int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
849d1d35e2fSjeremylt                                     CeedInt *blk_size) {
850d1d35e2fSjeremylt   *blk_size = rstr->blk_size;
851e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
852a681ae63Sjeremylt }
853a681ae63Sjeremylt 
854a681ae63Sjeremylt /**
855d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
8561469ee4dSjeremylt 
8571469ee4dSjeremylt   @param rstr       CeedElemRestriction
858d1d35e2fSjeremylt   @param[out] mult  Vector to store multiplicity (of size l_size)
8591469ee4dSjeremylt 
8601469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
8611469ee4dSjeremylt 
8627a982d89SJeremy L. Thompson   @ref User
8631469ee4dSjeremylt **/
8641469ee4dSjeremylt int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr,
8651469ee4dSjeremylt                                        CeedVector mult) {
8661469ee4dSjeremylt   int ierr;
867d1d35e2fSjeremylt   CeedVector e_vec;
8681469ee4dSjeremylt 
869d1d35e2fSjeremylt   // Create and set e_vec
870d1d35e2fSjeremylt   ierr = CeedElemRestrictionCreateVector(rstr, NULL, &e_vec); CeedChk(ierr);
871d1d35e2fSjeremylt   ierr = CeedVectorSetValue(e_vec, 1.0); CeedChk(ierr);
872fa9eac48SJed Brown   ierr = CeedVectorSetValue(mult, 0.0); CeedChk(ierr);
8731469ee4dSjeremylt 
8741469ee4dSjeremylt   // Apply to get multiplicity
875d1d35e2fSjeremylt   ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult,
876efc78312Sjeremylt                                   CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
8771469ee4dSjeremylt 
8781469ee4dSjeremylt   // Cleanup
879d1d35e2fSjeremylt   ierr = CeedVectorDestroy(&e_vec); CeedChk(ierr);
880e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
8811469ee4dSjeremylt }
8821469ee4dSjeremylt 
8831469ee4dSjeremylt /**
884f02ca4a2SJed Brown   @brief View a CeedElemRestriction
885f02ca4a2SJed Brown 
886f02ca4a2SJed Brown   @param[in] rstr    CeedElemRestriction to view
887f02ca4a2SJed Brown   @param[in] stream  Stream to write; typically stdout/stderr or a file
888f02ca4a2SJed Brown 
889f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
890f02ca4a2SJed Brown 
8917a982d89SJeremy L. Thompson   @ref User
892f02ca4a2SJed Brown **/
893f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
8947509a596Sjeremylt   char stridesstr[500];
8957509a596Sjeremylt   if (rstr->strides)
8967509a596Sjeremylt     sprintf(stridesstr, "[%d, %d, %d]", rstr->strides[0], rstr->strides[1],
8977509a596Sjeremylt             rstr->strides[2]);
898d979a051Sjeremylt   else
899d1d35e2fSjeremylt     sprintf(stridesstr, "%d", rstr->comp_stride);
9007509a596Sjeremylt 
9010036de2cSjeremylt   fprintf(stream, "%sCeedElemRestriction from (%d, %d) to %d elements with %d "
902d1d35e2fSjeremylt           "nodes each and %s %s\n", rstr->blk_size > 1 ? "Blocked " : "",
903d1d35e2fSjeremylt           rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
904d979a051Sjeremylt           rstr->strides ? "strides" : "component stride", stridesstr);
905e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
906f02ca4a2SJed Brown }
907f02ca4a2SJed Brown 
908f02ca4a2SJed Brown /**
909b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
910b11c1e72Sjeremylt 
9114ce2993fSjeremylt   @param rstr  CeedElemRestriction to destroy
912b11c1e72Sjeremylt 
913b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
914dfdf5a53Sjeremylt 
9157a982d89SJeremy L. Thompson   @ref User
916b11c1e72Sjeremylt **/
9174ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
918d7b241e6Sjeremylt   int ierr;
919d7b241e6Sjeremylt 
920d1d35e2fSjeremylt   if (!*rstr || --(*rstr)->ref_count > 0) return CEED_ERROR_SUCCESS;
921d1d35e2fSjeremylt   if ((*rstr)->num_readers)
9228229195eSjeremylt     // LCOV_EXCL_START
923e15f9bd0SJeremy L Thompson     return CeedError((*rstr)->ceed, CEED_ERROR_ACCESS,
924e15f9bd0SJeremy L Thompson                      "Cannot destroy CeedElemRestriction, "
925430758c8SJeremy L Thompson                      "a process has read access to the offset data");
9268229195eSjeremylt   // LCOV_EXCL_STOP
9274ce2993fSjeremylt   if ((*rstr)->Destroy) {
9284ce2993fSjeremylt     ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr);
929d7b241e6Sjeremylt   }
9307509a596Sjeremylt   ierr = CeedFree(&(*rstr)->strides); CeedChk(ierr);
9314ce2993fSjeremylt   ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr);
9324ce2993fSjeremylt   ierr = CeedFree(rstr); CeedChk(ierr);
933e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
934d7b241e6Sjeremylt }
935d7b241e6Sjeremylt 
936d7b241e6Sjeremylt /// @}
937