xref: /libCEED/interface/ceed-elemrestriction.c (revision 34359f16efbc10f0e69405f262a23387c38de222)
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 /**
717a982d89SJeremy L. Thompson   @brief Get the Ceed associated with a CeedElemRestriction
727a982d89SJeremy L. Thompson 
737a982d89SJeremy L. Thompson   @param rstr       CeedElemRestriction
747a982d89SJeremy L. Thompson   @param[out] ceed  Variable to store Ceed
757a982d89SJeremy L. Thompson 
767a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
777a982d89SJeremy L. Thompson 
787a982d89SJeremy L. Thompson   @ref Backend
797a982d89SJeremy L. Thompson **/
807a982d89SJeremy L. Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
817a982d89SJeremy L. Thompson   *ceed = rstr->ceed;
82e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
837a982d89SJeremy L. Thompson }
847a982d89SJeremy L. Thompson 
857a982d89SJeremy L. Thompson /**
86a681ae63Sjeremylt 
87a681ae63Sjeremylt   @brief Get the strides of a strided CeedElemRestriction
887a982d89SJeremy L. Thompson 
897a982d89SJeremy L. Thompson   @param rstr          CeedElemRestriction
90a681ae63Sjeremylt   @param[out] strides  Variable to store strides array
917a982d89SJeremy L. Thompson 
927a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
937a982d89SJeremy L. Thompson 
947a982d89SJeremy L. Thompson   @ref Backend
957a982d89SJeremy L. Thompson **/
96a681ae63Sjeremylt int CeedElemRestrictionGetStrides(CeedElemRestriction rstr,
97a681ae63Sjeremylt                                   CeedInt (*strides)[3]) {
98a681ae63Sjeremylt   if (!rstr->strides)
99a681ae63Sjeremylt     // LCOV_EXCL_START
100e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_MINOR,
101e15f9bd0SJeremy L Thompson                      "ElemRestriction has no stride data");
102a681ae63Sjeremylt   // LCOV_EXCL_STOP
103a681ae63Sjeremylt 
104a681ae63Sjeremylt   for (int i=0; i<3; i++)
105a681ae63Sjeremylt     (*strides)[i] = rstr->strides[i];
106e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1077a982d89SJeremy L. Thompson }
1087a982d89SJeremy L. Thompson 
1097a982d89SJeremy L. Thompson /**
110bd33150aSjeremylt   @brief Get read-only access to a CeedElemRestriction offsets array by memtype
111bd33150aSjeremylt 
112bd33150aSjeremylt   @param rstr          CeedElemRestriction to retrieve offsets
113d1d35e2fSjeremylt   @param mem_type      Memory type on which to access the array.  If the backend
114bd33150aSjeremylt                          uses a different memory type, this will perform a copy
115bd33150aSjeremylt                          (possibly cached).
116d1d35e2fSjeremylt   @param[out] offsets  Array on memory type mem_type
117bd33150aSjeremylt 
118bd33150aSjeremylt   @return An error code: 0 - success, otherwise - failure
119bd33150aSjeremylt 
120bd33150aSjeremylt   @ref User
121bd33150aSjeremylt **/
122d1d35e2fSjeremylt int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr,
123d1d35e2fSjeremylt                                   CeedMemType mem_type,
124bd33150aSjeremylt                                   const CeedInt **offsets) {
125bd33150aSjeremylt   int ierr;
126bd33150aSjeremylt 
127bd33150aSjeremylt   if (!rstr->GetOffsets)
128bd33150aSjeremylt     // LCOV_EXCL_START
129e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_UNSUPPORTED,
130e15f9bd0SJeremy L Thompson                      "Backend does not support GetOffsets");
131bd33150aSjeremylt   // LCOV_EXCL_STOP
132bd33150aSjeremylt 
133d1d35e2fSjeremylt   ierr = rstr->GetOffsets(rstr, mem_type, offsets); CeedChk(ierr);
134d1d35e2fSjeremylt   rstr->num_readers++;
135e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
136430758c8SJeremy L Thompson }
137430758c8SJeremy L Thompson 
138430758c8SJeremy L Thompson /**
139430758c8SJeremy L Thompson   @brief Restore an offsets array obtained using CeedElemRestrictionGetOffsets()
140430758c8SJeremy L Thompson 
141430758c8SJeremy L Thompson   @param rstr     CeedElemRestriction to restore
142430758c8SJeremy L Thompson   @param offsets  Array of offset data
143430758c8SJeremy L Thompson 
144430758c8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
145430758c8SJeremy L Thompson 
146430758c8SJeremy L Thompson   @ref User
147430758c8SJeremy L Thompson **/
148430758c8SJeremy L Thompson int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr,
149430758c8SJeremy L Thompson                                       const CeedInt **offsets) {
150430758c8SJeremy L Thompson   *offsets = NULL;
151d1d35e2fSjeremylt   rstr->num_readers--;
152e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
153bd33150aSjeremylt }
154bd33150aSjeremylt 
155bd33150aSjeremylt /**
1563ac43b2cSJeremy L Thompson   @brief Get the strided status of a CeedElemRestriction
1573ac43b2cSJeremy L Thompson 
1583ac43b2cSJeremy L Thompson   @param rstr             CeedElemRestriction
159d1d35e2fSjeremylt   @param[out] is_strided  Variable to store strided status, 1 if strided else 0
1603ac43b2cSJeremy L Thompson 
1613ac43b2cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1623ac43b2cSJeremy L Thompson 
1633ac43b2cSJeremy L Thompson   @ref Backend
1643ac43b2cSJeremy L Thompson **/
165d1d35e2fSjeremylt int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) {
166d1d35e2fSjeremylt   *is_strided = rstr->strides ? true : false;
167e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1683ac43b2cSJeremy L Thompson }
1693ac43b2cSJeremy L Thompson 
1703ac43b2cSJeremy L Thompson /**
171a681ae63Sjeremylt   @brief Get the backend stride status of a CeedElemRestriction
1727a982d89SJeremy L. Thompson 
1737a982d89SJeremy L. Thompson   @param rstr         CeedElemRestriction
174a681ae63Sjeremylt   @param[out] status  Variable to store stride status
1757a982d89SJeremy L. Thompson 
1767a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1777a982d89SJeremy L. Thompson 
1787a982d89SJeremy L. Thompson   @ref Backend
1797a982d89SJeremy L. Thompson **/
180fd364f38SJeremy L Thompson int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr,
181d1d35e2fSjeremylt     bool *has_backend_strides) {
182a681ae63Sjeremylt   if (!rstr->strides)
183a681ae63Sjeremylt     // LCOV_EXCL_START
184e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_MINOR,
185e15f9bd0SJeremy L Thompson                      "ElemRestriction has no stride data");
186a681ae63Sjeremylt   // LCOV_EXCL_STOP
1877a982d89SJeremy L. Thompson 
188d1d35e2fSjeremylt   *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) &&
189a681ae63Sjeremylt                           (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
190a681ae63Sjeremylt                           (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
191e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1927a982d89SJeremy L. Thompson }
1937a982d89SJeremy L. Thompson 
1947a982d89SJeremy L. Thompson /**
19549fd234cSJeremy L Thompson 
19649fd234cSJeremy L Thompson   @brief Get the E-vector layout of a CeedElemRestriction
19749fd234cSJeremy L Thompson 
19849fd234cSJeremy L Thompson   @param rstr         CeedElemRestriction
19949fd234cSJeremy L Thompson   @param[out] layout  Variable to store layout array,
20049fd234cSJeremy L Thompson                         stored as [nodes, components, elements].
20149fd234cSJeremy L Thompson                         The data for node i, component j, element k in the
20249fd234cSJeremy L Thompson                         E-vector is given by
20395e93d34SJeremy L Thompson                         i*layout[0] + j*layout[1] + k*layout[2]
20449fd234cSJeremy L Thompson 
20549fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
20649fd234cSJeremy L Thompson 
20749fd234cSJeremy L Thompson   @ref Backend
20849fd234cSJeremy L Thompson **/
20949fd234cSJeremy L Thompson int CeedElemRestrictionGetELayout(CeedElemRestriction rstr,
21049fd234cSJeremy L Thompson                                   CeedInt (*layout)[3]) {
21149fd234cSJeremy L Thompson   if (!rstr->layout[0])
21249fd234cSJeremy L Thompson     // LCOV_EXCL_START
213e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_MINOR,
214e15f9bd0SJeremy L Thompson                      "ElemRestriction has no layout data");
21549fd234cSJeremy L Thompson   // LCOV_EXCL_STOP
21649fd234cSJeremy L Thompson 
21749fd234cSJeremy L Thompson   for (int i=0; i<3; i++)
21849fd234cSJeremy L Thompson     (*layout)[i] = rstr->layout[i];
219e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
22049fd234cSJeremy L Thompson }
22149fd234cSJeremy L Thompson 
22249fd234cSJeremy L Thompson /**
22349fd234cSJeremy L Thompson 
22449fd234cSJeremy L Thompson   @brief Set the E-vector layout of a CeedElemRestriction
22549fd234cSJeremy L Thompson 
22649fd234cSJeremy L Thompson   @param rstr    CeedElemRestriction
22749fd234cSJeremy L Thompson   @param layout  Variable to containing layout array,
22849fd234cSJeremy L Thompson                    stored as [nodes, components, elements].
22949fd234cSJeremy L Thompson                    The data for node i, component j, element k in the
23049fd234cSJeremy L Thompson                    E-vector is given by
23195e93d34SJeremy L Thompson                    i*layout[0] + j*layout[1] + k*layout[2]
23249fd234cSJeremy L Thompson 
23349fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
23449fd234cSJeremy L Thompson 
23549fd234cSJeremy L Thompson   @ref Backend
23649fd234cSJeremy L Thompson **/
23749fd234cSJeremy L Thompson int CeedElemRestrictionSetELayout(CeedElemRestriction rstr,
23849fd234cSJeremy L Thompson                                   CeedInt layout[3]) {
23949fd234cSJeremy L Thompson   for (int i = 0; i<3; i++)
24049fd234cSJeremy L Thompson     rstr->layout[i] = layout[i];
241e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
24249fd234cSJeremy L Thompson }
24349fd234cSJeremy L Thompson 
24449fd234cSJeremy L Thompson /**
2457a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedElemRestriction
2467a982d89SJeremy L. Thompson 
2477a982d89SJeremy L. Thompson   @param rstr       CeedElemRestriction
2487a982d89SJeremy L. Thompson   @param[out] data  Variable to store data
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 CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) {
255777ff853SJeremy L Thompson   *(void **)data = rstr->data;
256e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2577a982d89SJeremy L. Thompson }
2587a982d89SJeremy L. Thompson 
2597a982d89SJeremy L. Thompson /**
2607a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedElemRestriction
2617a982d89SJeremy L. Thompson 
2627a982d89SJeremy L. Thompson   @param[out] rstr  CeedElemRestriction
2637a982d89SJeremy L. Thompson   @param data       Data to set
2647a982d89SJeremy L. Thompson 
2657a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2667a982d89SJeremy L. Thompson 
2677a982d89SJeremy L. Thompson   @ref Backend
2687a982d89SJeremy L. Thompson **/
269777ff853SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) {
270777ff853SJeremy L Thompson   rstr->data = data;
271e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2727a982d89SJeremy L. Thompson }
2737a982d89SJeremy L. Thompson 
274*34359f16Sjeremylt /**
275*34359f16Sjeremylt   @brief Increment the reference counter for a CeedElemRestriction
276*34359f16Sjeremylt 
277*34359f16Sjeremylt   @param rstr  ElemRestriction to increment the reference counter
278*34359f16Sjeremylt 
279*34359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
280*34359f16Sjeremylt 
281*34359f16Sjeremylt   @ref Backend
282*34359f16Sjeremylt **/
283*34359f16Sjeremylt int CeedElemRestrictionIncrementRefCounter(CeedElemRestriction rstr) {
284*34359f16Sjeremylt   rstr->ref_count++;
285*34359f16Sjeremylt   return CEED_ERROR_SUCCESS;
286*34359f16Sjeremylt }
287*34359f16Sjeremylt 
2887a982d89SJeremy L. Thompson /// @}
2897a982d89SJeremy L. Thompson 
29015910d16Sjeremylt /// @cond DOXYGEN_SKIP
29115910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
29215910d16Sjeremylt /// @endcond
29315910d16Sjeremylt 
2947a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
2957a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
2967a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
2977a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
298d7b241e6Sjeremylt /// @{
299d7b241e6Sjeremylt 
3007a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
3017a982d89SJeremy L. Thompson const CeedInt CEED_STRIDES_BACKEND[3] = {};
3027a982d89SJeremy L. Thompson 
3034cc79fe7SJed Brown /// Indicate that no CeedElemRestriction is provided by the user
3047a982d89SJeremy L. Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE =
3057a982d89SJeremy L. Thompson   &ceed_elemrestriction_none;
3067a982d89SJeremy L. Thompson 
307d7b241e6Sjeremylt /**
308b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
309d7b241e6Sjeremylt 
310b11c1e72Sjeremylt   @param ceed         A Ceed object where the CeedElemRestriction will be created
311d1d35e2fSjeremylt   @param num_elem     Number of elements described in the @a offsets array
312d1d35e2fSjeremylt   @param elem_size    Size (number of "nodes") per element
313d1d35e2fSjeremylt   @param num_comp     Number of field components per interpolation node
31495bb1877Svaleriabarra                         (1 for scalar fields)
315d1d35e2fSjeremylt   @param comp_stride  Stride between components for the same L-vector "node".
31695e93d34SJeremy L Thompson                         Data for node i, component j, element k can be found in
31795e93d34SJeremy L Thompson                         the L-vector at index
318d1d35e2fSjeremylt                         offsets[i + k*elem_size] + j*comp_stride.
319d1d35e2fSjeremylt   @param l_size       The size of the L-vector. This vector may be larger than
320d979a051Sjeremylt                         the elements and fields given by this restriction.
321d1d35e2fSjeremylt   @param mem_type     Memory type of the @a offsets array, see CeedMemType
322d1d35e2fSjeremylt   @param copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
323d1d35e2fSjeremylt   @param offsets      Array of shape [@a num_elem, @a elem_size]. Row i holds the
324d979a051Sjeremylt                         ordered list of the offsets (into the input CeedVector)
3258795c945Sjeremylt                         for the unknowns corresponding to element i, where
326d1d35e2fSjeremylt                         0 <= i < @a num_elem. All offsets must be in the range
327d1d35e2fSjeremylt                         [0, @a l_size - 1].
3284ce2993fSjeremylt   @param[out] rstr    Address of the variable where the newly created
329b11c1e72Sjeremylt                         CeedElemRestriction will be stored
330d7b241e6Sjeremylt 
331b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
332dfdf5a53Sjeremylt 
3337a982d89SJeremy L. Thompson   @ref User
334b11c1e72Sjeremylt **/
335d1d35e2fSjeremylt int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size,
336d1d35e2fSjeremylt                               CeedInt num_comp, CeedInt comp_stride,
337d1d35e2fSjeremylt                               CeedInt l_size, CeedMemType mem_type,
338d1d35e2fSjeremylt                               CeedCopyMode copy_mode, const CeedInt *offsets,
3394ce2993fSjeremylt                               CeedElemRestriction *rstr) {
340d7b241e6Sjeremylt   int ierr;
341d7b241e6Sjeremylt 
3425fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
3435fe0d4faSjeremylt     Ceed delegate;
344aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
345aefd8378Sjeremylt     CeedChk(ierr);
3465fe0d4faSjeremylt 
3475fe0d4faSjeremylt     if (!delegate)
348c042f62fSJeremy L Thompson       // LCOV_EXCL_START
349e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
350e15f9bd0SJeremy L Thompson                        "Backend does not support ElemRestrictionCreate");
351c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
3525fe0d4faSjeremylt 
353d1d35e2fSjeremylt     ierr = CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp,
354d1d35e2fSjeremylt                                      comp_stride, l_size, mem_type, copy_mode,
355d979a051Sjeremylt                                      offsets, rstr); CeedChk(ierr);
356e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
3575fe0d4faSjeremylt   }
3585fe0d4faSjeremylt 
3594ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
3604ce2993fSjeremylt   (*rstr)->ceed = ceed;
361*34359f16Sjeremylt   ierr = CeedIncrementRefCounter(ceed); CeedChk(ierr);
362d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
363d1d35e2fSjeremylt   (*rstr)->num_elem = num_elem;
364d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
365d1d35e2fSjeremylt   (*rstr)->num_comp = num_comp;
366d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
367d1d35e2fSjeremylt   (*rstr)->l_size = l_size;
368d1d35e2fSjeremylt   (*rstr)->num_blk = num_elem;
369d1d35e2fSjeremylt   (*rstr)->blk_size = 1;
370d1d35e2fSjeremylt   ierr = ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, *rstr);
371d979a051Sjeremylt   CeedChk(ierr);
372e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
373d7b241e6Sjeremylt }
374d7b241e6Sjeremylt 
375d7b241e6Sjeremylt /**
3767509a596Sjeremylt   @brief Create a strided CeedElemRestriction
377d7b241e6Sjeremylt 
378b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
379d1d35e2fSjeremylt   @param num_elem   Number of elements described by the restriction
380d1d35e2fSjeremylt   @param elem_size  Size (number of "nodes") per element
381d1d35e2fSjeremylt   @param num_comp   Number of field components per interpolation "node"
38295bb1877Svaleriabarra                       (1 for scalar fields)
383d1d35e2fSjeremylt   @param l_size     The size of the L-vector. This vector may be larger than
384d979a051Sjeremylt                       the elements and fields given by this restriction.
3857509a596Sjeremylt   @param strides    Array for strides between [nodes, components, elements].
38695e93d34SJeremy L Thompson                       Data for node i, component j, element k can be found in
38795e93d34SJeremy L Thompson                       the L-vector at index
38895e93d34SJeremy L Thompson                       i*strides[0] + j*strides[1] + k*strides[2].
38995e93d34SJeremy L Thompson                       @a CEED_STRIDES_BACKEND may be used with vectors created
39095e93d34SJeremy L Thompson                       by a Ceed backend.
3914ce2993fSjeremylt   @param rstr       Address of the variable where the newly created
392b11c1e72Sjeremylt                       CeedElemRestriction will be stored
393d7b241e6Sjeremylt 
394b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
395dfdf5a53Sjeremylt 
3967a982d89SJeremy L. Thompson   @ref User
397b11c1e72Sjeremylt **/
398d1d35e2fSjeremylt int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem,
399d1d35e2fSjeremylt                                      CeedInt elem_size,
400d1d35e2fSjeremylt                                      CeedInt num_comp, CeedInt l_size,
4018621c6c6SJeremy L Thompson                                      const CeedInt strides[3],
402f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
403d7b241e6Sjeremylt   int ierr;
404d7b241e6Sjeremylt 
4055fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
4065fe0d4faSjeremylt     Ceed delegate;
407aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
408aefd8378Sjeremylt     CeedChk(ierr);
4095fe0d4faSjeremylt 
4105fe0d4faSjeremylt     if (!delegate)
411c042f62fSJeremy L Thompson       // LCOV_EXCL_START
412e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
413e15f9bd0SJeremy L Thompson                        "Backend does not support ElemRestrictionCreate");
414c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
4155fe0d4faSjeremylt 
416d1d35e2fSjeremylt     ierr = CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp,
417d1d35e2fSjeremylt                                             l_size, strides, rstr);
418d979a051Sjeremylt     CeedChk(ierr);
419e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
4205fe0d4faSjeremylt   }
4215fe0d4faSjeremylt 
4224ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
4234ce2993fSjeremylt   (*rstr)->ceed = ceed;
424*34359f16Sjeremylt   ierr = CeedIncrementRefCounter(ceed); CeedChk(ierr);
425d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
426d1d35e2fSjeremylt   (*rstr)->num_elem = num_elem;
427d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
428d1d35e2fSjeremylt   (*rstr)->num_comp = num_comp;
429d1d35e2fSjeremylt   (*rstr)->l_size = l_size;
430d1d35e2fSjeremylt   (*rstr)->num_blk = num_elem;
431d1d35e2fSjeremylt   (*rstr)->blk_size = 1;
4327509a596Sjeremylt   ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr);
4337509a596Sjeremylt   for (int i=0; i<3; i++)
4347509a596Sjeremylt     (*rstr)->strides[i] = strides[i];
4351dfeef1dSjeremylt   ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL,
4361dfeef1dSjeremylt                                      *rstr);
4374b8bea3bSJed Brown   CeedChk(ierr);
438e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
439d7b241e6Sjeremylt }
440d7b241e6Sjeremylt 
441d7b241e6Sjeremylt /**
442b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
443d7b241e6Sjeremylt 
444d7b241e6Sjeremylt   @param ceed         A Ceed object where the CeedElemRestriction will be created.
445d1d35e2fSjeremylt   @param num_elem     Number of elements described in the @a offsets array.
446d1d35e2fSjeremylt   @param elem_size    Size (number of unknowns) per element
447d1d35e2fSjeremylt   @param blk_size     Number of elements in a block
448d1d35e2fSjeremylt   @param num_comp     Number of field components per interpolation node
44995bb1877Svaleriabarra                         (1 for scalar fields)
450d1d35e2fSjeremylt   @param comp_stride  Stride between components for the same L-vector "node".
45195e93d34SJeremy L Thompson                         Data for node i, component j, element k can be found in
45295e93d34SJeremy L Thompson                         the L-vector at index
453d1d35e2fSjeremylt                         offsets[i + k*elem_size] + j*comp_stride.
454d1d35e2fSjeremylt   @param l_size       The size of the L-vector. This vector may be larger than
455d979a051Sjeremylt                         the elements and fields given by this restriction.
456d1d35e2fSjeremylt   @param mem_type     Memory type of the @a offsets array, see CeedMemType
457d1d35e2fSjeremylt   @param copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
458d1d35e2fSjeremylt   @param offsets      Array of shape [@a num_elem, @a elem_size]. Row i holds the
459d979a051Sjeremylt                         ordered list of the offsets (into the input CeedVector)
4608795c945Sjeremylt                         for the unknowns corresponding to element i, where
461d1d35e2fSjeremylt                         0 <= i < @a num_elem. All offsets must be in the range
462d1d35e2fSjeremylt                         [0, @a l_size - 1]. The backend will permute and pad this
4638795c945Sjeremylt                         array to the desired ordering for the blocksize, which is
4648795c945Sjeremylt                         typically given by the backend. The default reordering is
4658795c945Sjeremylt                         to interlace elements.
4664ce2993fSjeremylt   @param rstr         Address of the variable where the newly created
467b11c1e72Sjeremylt                         CeedElemRestriction will be stored
468d7b241e6Sjeremylt 
469b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
470dfdf5a53Sjeremylt 
4717a982d89SJeremy L. Thompson   @ref Backend
472b11c1e72Sjeremylt  **/
473d1d35e2fSjeremylt int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem,
474d1d35e2fSjeremylt                                      CeedInt elem_size,
475d1d35e2fSjeremylt                                      CeedInt blk_size, CeedInt num_comp,
476d1d35e2fSjeremylt                                      CeedInt comp_stride, CeedInt l_size,
477d1d35e2fSjeremylt                                      CeedMemType mem_type, CeedCopyMode copy_mode,
478d979a051Sjeremylt                                      const CeedInt *offsets,
4794ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
480d7b241e6Sjeremylt   int ierr;
481d1d35e2fSjeremylt   CeedInt *blk_offsets;
482d1d35e2fSjeremylt   CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
483d7b241e6Sjeremylt 
4845fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
4855fe0d4faSjeremylt     Ceed delegate;
486aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
487aefd8378Sjeremylt     CeedChk(ierr);
4885fe0d4faSjeremylt 
4895fe0d4faSjeremylt     if (!delegate)
490c042f62fSJeremy L Thompson       // LCOV_EXCL_START
491e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support "
4921d102b48SJeremy L Thompson                        "ElemRestrictionCreateBlocked");
493c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
4945fe0d4faSjeremylt 
495d1d35e2fSjeremylt     ierr = CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, blk_size,
496d1d35e2fSjeremylt                                             num_comp, comp_stride, l_size, mem_type,
497d1d35e2fSjeremylt                                             copy_mode, offsets, rstr);
498d979a051Sjeremylt     CeedChk(ierr);
499e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
5005fe0d4faSjeremylt   }
501d7b241e6Sjeremylt 
5024ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
503d7b241e6Sjeremylt 
504d1d35e2fSjeremylt   ierr = CeedCalloc(num_blk*blk_size*elem_size, &blk_offsets); CeedChk(ierr);
505d1d35e2fSjeremylt   ierr = CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size,
506d1d35e2fSjeremylt                                elem_size); CeedChk(ierr);
507d7b241e6Sjeremylt 
5084ce2993fSjeremylt   (*rstr)->ceed = ceed;
509*34359f16Sjeremylt   ierr = CeedIncrementRefCounter(ceed); CeedChk(ierr);
510d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
511d1d35e2fSjeremylt   (*rstr)->num_elem = num_elem;
512d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
513d1d35e2fSjeremylt   (*rstr)->num_comp = num_comp;
514d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
515d1d35e2fSjeremylt   (*rstr)->l_size = l_size;
516d1d35e2fSjeremylt   (*rstr)->num_blk = num_blk;
517d1d35e2fSjeremylt   (*rstr)->blk_size = blk_size;
518667bc5fcSjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
519d1d35e2fSjeremylt          (const CeedInt *) blk_offsets, *rstr); CeedChk(ierr);
520d1d35e2fSjeremylt   if (copy_mode == CEED_OWN_POINTER) {
521d979a051Sjeremylt     ierr = CeedFree(&offsets); CeedChk(ierr);
5221d102b48SJeremy L Thompson   }
523e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
524d7b241e6Sjeremylt }
525d7b241e6Sjeremylt 
526b11c1e72Sjeremylt /**
5277509a596Sjeremylt   @brief Create a blocked strided CeedElemRestriction
5287509a596Sjeremylt 
5297509a596Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
530d1d35e2fSjeremylt   @param num_elem   Number of elements described by the restriction
531d1d35e2fSjeremylt   @param elem_size  Size (number of "nodes") per element
532d1d35e2fSjeremylt   @param blk_size   Number of elements in a block
533d1d35e2fSjeremylt   @param num_comp   Number of field components per interpolation node
5347509a596Sjeremylt                       (1 for scalar fields)
535d1d35e2fSjeremylt   @param l_size     The size of the L-vector. This vector may be larger than
536d979a051Sjeremylt                       the elements and fields given by this restriction.
5377509a596Sjeremylt   @param strides    Array for strides between [nodes, components, elements].
53895e93d34SJeremy L Thompson                       Data for node i, component j, element k can be found in
53995e93d34SJeremy L Thompson                       the L-vector at index
54095e93d34SJeremy L Thompson                       i*strides[0] + j*strides[1] + k*strides[2].
54195e93d34SJeremy L Thompson                       @a CEED_STRIDES_BACKEND may be used with vectors created
54295e93d34SJeremy L Thompson                       by a Ceed backend.
5437509a596Sjeremylt   @param rstr       Address of the variable where the newly created
5447509a596Sjeremylt                       CeedElemRestriction will be stored
5457509a596Sjeremylt 
5467509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
5477509a596Sjeremylt 
5487a982d89SJeremy L. Thompson   @ref User
5497509a596Sjeremylt **/
550d1d35e2fSjeremylt int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem,
551d1d35e2fSjeremylt     CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedInt l_size,
5528621c6c6SJeremy L Thompson     const CeedInt strides[3], CeedElemRestriction *rstr) {
5537509a596Sjeremylt   int ierr;
554d1d35e2fSjeremylt   CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
5557509a596Sjeremylt 
5567509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
5577509a596Sjeremylt     Ceed delegate;
5587509a596Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
5597509a596Sjeremylt     CeedChk(ierr);
5607509a596Sjeremylt 
5617509a596Sjeremylt     if (!delegate)
5627509a596Sjeremylt       // LCOV_EXCL_START
563e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support "
5647509a596Sjeremylt                        "ElemRestrictionCreateBlocked");
5657509a596Sjeremylt     // LCOV_EXCL_STOP
5667509a596Sjeremylt 
567d1d35e2fSjeremylt     ierr = CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size,
568d1d35e2fSjeremylt            blk_size, num_comp, l_size, strides, rstr); CeedChk(ierr);
569e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
5707509a596Sjeremylt   }
5717509a596Sjeremylt 
5727509a596Sjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
5737509a596Sjeremylt 
5747509a596Sjeremylt   (*rstr)->ceed = ceed;
575*34359f16Sjeremylt   ierr = CeedIncrementRefCounter(ceed); CeedChk(ierr);
576d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
577d1d35e2fSjeremylt   (*rstr)->num_elem = num_elem;
578d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
579d1d35e2fSjeremylt   (*rstr)->num_comp = num_comp;
580d1d35e2fSjeremylt   (*rstr)->l_size = l_size;
581d1d35e2fSjeremylt   (*rstr)->num_blk = num_blk;
582d1d35e2fSjeremylt   (*rstr)->blk_size = blk_size;
5837509a596Sjeremylt   ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr);
5847509a596Sjeremylt   for (int i=0; i<3; i++)
5857509a596Sjeremylt     (*rstr)->strides[i] = strides[i];
5867509a596Sjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
5877509a596Sjeremylt          NULL, *rstr); CeedChk(ierr);
588e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5897509a596Sjeremylt }
5907509a596Sjeremylt 
5917509a596Sjeremylt /**
592b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
593b11c1e72Sjeremylt 
5944ce2993fSjeremylt   @param rstr   CeedElemRestriction
595d1d35e2fSjeremylt   @param l_vec  The address of the L-vector to be created, or NULL
596d1d35e2fSjeremylt   @param e_vec  The address of the E-vector to be created, or NULL
597b11c1e72Sjeremylt 
598b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
599dfdf5a53Sjeremylt 
6007a982d89SJeremy L. Thompson   @ref User
601b11c1e72Sjeremylt **/
602d1d35e2fSjeremylt int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec,
603d1d35e2fSjeremylt                                     CeedVector *e_vec) {
604d7b241e6Sjeremylt   int ierr;
605d1d35e2fSjeremylt   CeedInt e_size, l_size;
606d1d35e2fSjeremylt   l_size = rstr->l_size;
607d1d35e2fSjeremylt   e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
608d1d35e2fSjeremylt   if (l_vec) {
609d1d35e2fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, l_size, l_vec); CeedChk(ierr);
610d7b241e6Sjeremylt   }
611d1d35e2fSjeremylt   if (e_vec) {
612d1d35e2fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, e_size, e_vec); CeedChk(ierr);
613d7b241e6Sjeremylt   }
614e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
615d7b241e6Sjeremylt }
616d7b241e6Sjeremylt 
617d7b241e6Sjeremylt /**
618d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
619d7b241e6Sjeremylt 
6204ce2993fSjeremylt   @param rstr    CeedElemRestriction
621d1d35e2fSjeremylt   @param t_mode  Apply restriction or transpose
622d1d35e2fSjeremylt   @param u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
623d1d35e2fSjeremylt   @param ru      Output vector (of shape [@a num_elem * @a elem_size] when
624d1d35e2fSjeremylt                    t_mode=@ref CEED_NOTRANSPOSE). Ordering of the e-vector is decided
6257aaeacdcSjeremylt                    by the backend.
6264cc79fe7SJed Brown   @param request Request or @ref CEED_REQUEST_IMMEDIATE
627b11c1e72Sjeremylt 
628b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
629dfdf5a53Sjeremylt 
6307a982d89SJeremy L. Thompson   @ref User
631b11c1e72Sjeremylt **/
632d1d35e2fSjeremylt int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode,
633a8d32208Sjeremylt                              CeedVector u, CeedVector ru,
634a8d32208Sjeremylt                              CeedRequest *request) {
635d7b241e6Sjeremylt   CeedInt m, n;
636d7b241e6Sjeremylt   int ierr;
637d7b241e6Sjeremylt 
638d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
639d1d35e2fSjeremylt     m = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
640d1d35e2fSjeremylt     n = rstr->l_size;
641d7b241e6Sjeremylt   } else {
642d1d35e2fSjeremylt     m = rstr->l_size;
643d1d35e2fSjeremylt     n = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
644d7b241e6Sjeremylt   }
645d7b241e6Sjeremylt   if (n != u->length)
646c042f62fSJeremy L Thompson     // LCOV_EXCL_START
647e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
648e15f9bd0SJeremy L Thompson                      "Input vector size %d not compatible with "
6491d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
650c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
651a8d32208Sjeremylt   if (m != ru->length)
652c042f62fSJeremy L Thompson     // LCOV_EXCL_START
653e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
654e15f9bd0SJeremy L Thompson                      "Output vector size %d not compatible with "
655a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
656c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
657d1d35e2fSjeremylt   ierr = rstr->Apply(rstr, t_mode, u, ru, request); CeedChk(ierr);
658e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
659d7b241e6Sjeremylt }
660d7b241e6Sjeremylt 
661d7b241e6Sjeremylt /**
662d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
663be9261b7Sjeremylt 
664be9261b7Sjeremylt   @param rstr    CeedElemRestriction
6651f37b403Sjeremylt   @param block   Block number to restrict to/from, i.e. block=0 will handle
666d1d35e2fSjeremylt                    elements [0 : blk_size] and block=3 will handle elements
667d1d35e2fSjeremylt                    [3*blk_size : 4*blk_size]
668d1d35e2fSjeremylt   @param t_mode  Apply restriction or transpose
669d1d35e2fSjeremylt   @param u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
670d1d35e2fSjeremylt   @param ru      Output vector (of shape [@a blk_size * @a elem_size] when
671d1d35e2fSjeremylt                    t_mode=@ref CEED_NOTRANSPOSE). Ordering of the e-vector is decided
6727aaeacdcSjeremylt                    by the backend.
6734cc79fe7SJed Brown   @param request Request or @ref CEED_REQUEST_IMMEDIATE
674be9261b7Sjeremylt 
675be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
676be9261b7Sjeremylt 
6777a982d89SJeremy L. Thompson   @ref Backend
678be9261b7Sjeremylt **/
679be9261b7Sjeremylt int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block,
680d1d35e2fSjeremylt                                   CeedTransposeMode t_mode, CeedVector u,
681a8d32208Sjeremylt                                   CeedVector ru, CeedRequest *request) {
682be9261b7Sjeremylt   CeedInt m, n;
683be9261b7Sjeremylt   int ierr;
684be9261b7Sjeremylt 
685d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
686d1d35e2fSjeremylt     m = rstr->blk_size * rstr->elem_size * rstr->num_comp;
687d1d35e2fSjeremylt     n = rstr->l_size;
688be9261b7Sjeremylt   } else {
689d1d35e2fSjeremylt     m = rstr->l_size;
690d1d35e2fSjeremylt     n = rstr->blk_size * rstr->elem_size * rstr->num_comp;
691be9261b7Sjeremylt   }
692be9261b7Sjeremylt   if (n != u->length)
693c042f62fSJeremy L Thompson     // LCOV_EXCL_START
694e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
695e15f9bd0SJeremy L Thompson                      "Input vector size %d not compatible with "
6961d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
697c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
698a8d32208Sjeremylt   if (m != ru->length)
699c042f62fSJeremy L Thompson     // LCOV_EXCL_START
700e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
701e15f9bd0SJeremy L Thompson                      "Output vector size %d not compatible with "
702a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
703c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
704d1d35e2fSjeremylt   if (rstr->blk_size*block > rstr->num_elem)
705c042f62fSJeremy L Thompson     // LCOV_EXCL_START
706e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
707e15f9bd0SJeremy L Thompson                      "Cannot retrieve block %d, element %d > "
708d1d35e2fSjeremylt                      "total elements %d", block, rstr->blk_size*block,
709d1d35e2fSjeremylt                      rstr->num_elem);
710c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
711d1d35e2fSjeremylt   ierr = rstr->ApplyBlock(rstr, block, t_mode, u, ru, request);
712be9261b7Sjeremylt   CeedChk(ierr);
713e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
714be9261b7Sjeremylt }
715be9261b7Sjeremylt 
716be9261b7Sjeremylt /**
717d979a051Sjeremylt   @brief Get the L-vector component stride
718a681ae63Sjeremylt 
719a681ae63Sjeremylt   @param rstr              CeedElemRestriction
720d1d35e2fSjeremylt   @param[out] comp_stride  Variable to store component stride
721a681ae63Sjeremylt 
722a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
723a681ae63Sjeremylt 
724a681ae63Sjeremylt   @ref Backend
725a681ae63Sjeremylt **/
726d979a051Sjeremylt int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr,
727d1d35e2fSjeremylt                                      CeedInt *comp_stride) {
728d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
729e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
730a681ae63Sjeremylt }
731a681ae63Sjeremylt 
732a681ae63Sjeremylt /**
733a681ae63Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
734a681ae63Sjeremylt 
735a681ae63Sjeremylt   @param rstr           CeedElemRestriction
736d1d35e2fSjeremylt   @param[out] num_elem  Variable to store number of elements
737a681ae63Sjeremylt 
738a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
739a681ae63Sjeremylt 
740a681ae63Sjeremylt   @ref Backend
741a681ae63Sjeremylt **/
742a681ae63Sjeremylt int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
743d1d35e2fSjeremylt                                       CeedInt *num_elem) {
744d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
745e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
746a681ae63Sjeremylt }
747a681ae63Sjeremylt 
748a681ae63Sjeremylt /**
749a681ae63Sjeremylt   @brief Get the size of elements in the CeedElemRestriction
750a681ae63Sjeremylt 
751a681ae63Sjeremylt   @param rstr            CeedElemRestriction
752d1d35e2fSjeremylt   @param[out] elem_size  Variable to store size of elements
753a681ae63Sjeremylt 
754a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
755a681ae63Sjeremylt 
756a681ae63Sjeremylt   @ref Backend
757a681ae63Sjeremylt **/
758a681ae63Sjeremylt int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
759d1d35e2fSjeremylt                                       CeedInt *elem_size) {
760d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
761e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
762a681ae63Sjeremylt }
763a681ae63Sjeremylt 
764a681ae63Sjeremylt /**
765d979a051Sjeremylt   @brief Get the size of the l-vector for a CeedElemRestriction
766a681ae63Sjeremylt 
767a681ae63Sjeremylt   @param rstr         CeedElemRestriction
768d1d35e2fSjeremylt   @param[out] l_size  Variable to store number of nodes
769a681ae63Sjeremylt 
770a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
771a681ae63Sjeremylt 
772a681ae63Sjeremylt   @ref Backend
773a681ae63Sjeremylt **/
774d979a051Sjeremylt int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr,
775d1d35e2fSjeremylt                                       CeedInt *l_size) {
776d1d35e2fSjeremylt   *l_size = rstr->l_size;
777e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
778a681ae63Sjeremylt }
779a681ae63Sjeremylt 
780a681ae63Sjeremylt /**
781a681ae63Sjeremylt   @brief Get the number of components in the elements of a
782a681ae63Sjeremylt          CeedElemRestriction
783a681ae63Sjeremylt 
784a681ae63Sjeremylt   @param rstr           CeedElemRestriction
785d1d35e2fSjeremylt   @param[out] num_comp  Variable to store number of components
786a681ae63Sjeremylt 
787a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
788a681ae63Sjeremylt 
789a681ae63Sjeremylt   @ref Backend
790a681ae63Sjeremylt **/
791a681ae63Sjeremylt int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
792d1d35e2fSjeremylt                                         CeedInt *num_comp) {
793d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
794e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
795a681ae63Sjeremylt }
796a681ae63Sjeremylt 
797a681ae63Sjeremylt /**
798a681ae63Sjeremylt   @brief Get the number of blocks in a CeedElemRestriction
799a681ae63Sjeremylt 
800a681ae63Sjeremylt   @param rstr            CeedElemRestriction
801d1d35e2fSjeremylt   @param[out] num_block  Variable to store number of blocks
802a681ae63Sjeremylt 
803a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
804a681ae63Sjeremylt 
805a681ae63Sjeremylt   @ref Backend
806a681ae63Sjeremylt **/
807a681ae63Sjeremylt int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
808d1d35e2fSjeremylt                                     CeedInt *num_block) {
809d1d35e2fSjeremylt   *num_block = rstr->num_blk;
810e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
811a681ae63Sjeremylt }
812a681ae63Sjeremylt 
813a681ae63Sjeremylt /**
814a681ae63Sjeremylt   @brief Get the size of blocks in the CeedElemRestriction
815a681ae63Sjeremylt 
816a681ae63Sjeremylt   @param rstr           CeedElemRestriction
817d1d35e2fSjeremylt   @param[out] blk_size  Variable to store size of blocks
818a681ae63Sjeremylt 
819a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
820a681ae63Sjeremylt 
821a681ae63Sjeremylt   @ref Backend
822a681ae63Sjeremylt **/
823a681ae63Sjeremylt int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
824d1d35e2fSjeremylt                                     CeedInt *blk_size) {
825d1d35e2fSjeremylt   *blk_size = rstr->blk_size;
826e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
827a681ae63Sjeremylt }
828a681ae63Sjeremylt 
829a681ae63Sjeremylt /**
830d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
8311469ee4dSjeremylt 
8321469ee4dSjeremylt   @param rstr       CeedElemRestriction
833d1d35e2fSjeremylt   @param[out] mult  Vector to store multiplicity (of size l_size)
8341469ee4dSjeremylt 
8351469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
8361469ee4dSjeremylt 
8377a982d89SJeremy L. Thompson   @ref User
8381469ee4dSjeremylt **/
8391469ee4dSjeremylt int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr,
8401469ee4dSjeremylt                                        CeedVector mult) {
8411469ee4dSjeremylt   int ierr;
842d1d35e2fSjeremylt   CeedVector e_vec;
8431469ee4dSjeremylt 
844d1d35e2fSjeremylt   // Create and set e_vec
845d1d35e2fSjeremylt   ierr = CeedElemRestrictionCreateVector(rstr, NULL, &e_vec); CeedChk(ierr);
846d1d35e2fSjeremylt   ierr = CeedVectorSetValue(e_vec, 1.0); CeedChk(ierr);
847fa9eac48SJed Brown   ierr = CeedVectorSetValue(mult, 0.0); CeedChk(ierr);
8481469ee4dSjeremylt 
8491469ee4dSjeremylt   // Apply to get multiplicity
850d1d35e2fSjeremylt   ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult,
851efc78312Sjeremylt                                   CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
8521469ee4dSjeremylt 
8531469ee4dSjeremylt   // Cleanup
854d1d35e2fSjeremylt   ierr = CeedVectorDestroy(&e_vec); CeedChk(ierr);
855e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
8561469ee4dSjeremylt }
8571469ee4dSjeremylt 
8581469ee4dSjeremylt /**
859f02ca4a2SJed Brown   @brief View a CeedElemRestriction
860f02ca4a2SJed Brown 
861f02ca4a2SJed Brown   @param[in] rstr    CeedElemRestriction to view
862f02ca4a2SJed Brown   @param[in] stream  Stream to write; typically stdout/stderr or a file
863f02ca4a2SJed Brown 
864f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
865f02ca4a2SJed Brown 
8667a982d89SJeremy L. Thompson   @ref User
867f02ca4a2SJed Brown **/
868f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
8697509a596Sjeremylt   char stridesstr[500];
8707509a596Sjeremylt   if (rstr->strides)
8717509a596Sjeremylt     sprintf(stridesstr, "[%d, %d, %d]", rstr->strides[0], rstr->strides[1],
8727509a596Sjeremylt             rstr->strides[2]);
873d979a051Sjeremylt   else
874d1d35e2fSjeremylt     sprintf(stridesstr, "%d", rstr->comp_stride);
8757509a596Sjeremylt 
8760036de2cSjeremylt   fprintf(stream, "%sCeedElemRestriction from (%d, %d) to %d elements with %d "
877d1d35e2fSjeremylt           "nodes each and %s %s\n", rstr->blk_size > 1 ? "Blocked " : "",
878d1d35e2fSjeremylt           rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
879d979a051Sjeremylt           rstr->strides ? "strides" : "component stride", stridesstr);
880e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
881f02ca4a2SJed Brown }
882f02ca4a2SJed Brown 
883f02ca4a2SJed Brown /**
884b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
885b11c1e72Sjeremylt 
8864ce2993fSjeremylt   @param rstr  CeedElemRestriction to destroy
887b11c1e72Sjeremylt 
888b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
889dfdf5a53Sjeremylt 
8907a982d89SJeremy L. Thompson   @ref User
891b11c1e72Sjeremylt **/
8924ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
893d7b241e6Sjeremylt   int ierr;
894d7b241e6Sjeremylt 
895d1d35e2fSjeremylt   if (!*rstr || --(*rstr)->ref_count > 0) return CEED_ERROR_SUCCESS;
896d1d35e2fSjeremylt   if ((*rstr)->num_readers)
897e15f9bd0SJeremy L Thompson     return CeedError((*rstr)->ceed, CEED_ERROR_ACCESS,
898e15f9bd0SJeremy L Thompson                      "Cannot destroy CeedElemRestriction, "
899430758c8SJeremy L Thompson                      "a process has read access to the offset data");
9004ce2993fSjeremylt   if ((*rstr)->Destroy) {
9014ce2993fSjeremylt     ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr);
902d7b241e6Sjeremylt   }
9037509a596Sjeremylt   ierr = CeedFree(&(*rstr)->strides); CeedChk(ierr);
9044ce2993fSjeremylt   ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr);
9054ce2993fSjeremylt   ierr = CeedFree(rstr); CeedChk(ierr);
906e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
907d7b241e6Sjeremylt }
908d7b241e6Sjeremylt 
909d7b241e6Sjeremylt /// @}
910