xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-elemrestriction.c (revision 52b3e6a738faffda5b45f08b3021a8d767a770af)
13d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3d7b241e6Sjeremylt //
43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
5d7b241e6Sjeremylt //
63d8e8822SJeremy L Thompson // This file is part of CEED:  http://github.com/ceed
7d7b241e6Sjeremylt 
8ec3da8bcSJed Brown #include <ceed/ceed.h>
9ec3da8bcSJed Brown #include <ceed/backend.h>
103d576824SJeremy L Thompson #include <ceed-impl.h>
113d576824SJeremy L Thompson #include <stdbool.h>
123d576824SJeremy L Thompson #include <stdio.h>
13d7b241e6Sjeremylt 
147a982d89SJeremy L. Thompson /// @file
157a982d89SJeremy L. Thompson /// Implementation of CeedElemRestriction interfaces
167a982d89SJeremy L. Thompson 
177a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
187a982d89SJeremy L. Thompson /// CeedElemRestriction Library Internal Functions
197a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
207a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionDeveloper
217a982d89SJeremy L. Thompson /// @{
227a982d89SJeremy L. Thompson 
237a982d89SJeremy L. Thompson /**
24d979a051Sjeremylt   @brief Permute and pad offsets for a blocked restriction
257a982d89SJeremy L. Thompson 
26d1d35e2fSjeremylt   @param offsets     Array of shape [@a num_elem, @a elem_size]. Row i holds the
27d979a051Sjeremylt                        ordered list of the offsets (into the input CeedVector)
287a982d89SJeremy L. Thompson                        for the unknowns corresponding to element i, where
29d1d35e2fSjeremylt                        0 <= i < @a num_elem. All offsets must be in the range
30d1d35e2fSjeremylt                        [0, @a l_size - 1].
31d1d35e2fSjeremylt   @param blk_offsets Array of permuted and padded offsets of
32d1d35e2fSjeremylt                        shape [@a num_blk, @a elem_size, @a blk_size].
33d1d35e2fSjeremylt   @param num_blk     Number of blocks
34d1d35e2fSjeremylt   @param num_elem    Number of elements
35d1d35e2fSjeremylt   @param blk_size    Number of elements in a block
36d1d35e2fSjeremylt   @param elem_size   Size of each element
377a982d89SJeremy L. Thompson 
387a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
397a982d89SJeremy L. Thompson 
407a982d89SJeremy L. Thompson   @ref Utility
417a982d89SJeremy L. Thompson **/
42d1d35e2fSjeremylt int CeedPermutePadOffsets(const CeedInt *offsets, CeedInt *blk_offsets,
43d1d35e2fSjeremylt                           CeedInt num_blk, CeedInt num_elem, CeedInt blk_size,
44d1d35e2fSjeremylt                           CeedInt elem_size) {
45d1d35e2fSjeremylt   for (CeedInt e=0; e<num_blk*blk_size; e+=blk_size)
4692ae7e47SJeremy L Thompson     for (CeedInt j=0; j<blk_size; j++)
4792ae7e47SJeremy L Thompson       for (CeedInt k=0; k<elem_size; k++)
48d1d35e2fSjeremylt         blk_offsets[e*elem_size + k*blk_size + j]
49d1d35e2fSjeremylt           = offsets[CeedIntMin(e+j,num_elem-1)*elem_size + k];
50e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
517a982d89SJeremy L. Thompson }
527a982d89SJeremy L. Thompson 
537a982d89SJeremy L. Thompson /// @}
547a982d89SJeremy L. Thompson 
557a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
567a982d89SJeremy L. Thompson /// CeedElemRestriction Backend API
577a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
587a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionBackend
597a982d89SJeremy L. Thompson /// @{
607a982d89SJeremy L. Thompson 
617a982d89SJeremy L. Thompson /**
62a681ae63Sjeremylt 
63a681ae63Sjeremylt   @brief Get the strides of a strided CeedElemRestriction
647a982d89SJeremy L. Thompson 
657a982d89SJeremy L. Thompson   @param rstr          CeedElemRestriction
66a681ae63Sjeremylt   @param[out] strides  Variable to store strides array
677a982d89SJeremy L. Thompson 
687a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
697a982d89SJeremy L. Thompson 
707a982d89SJeremy L. Thompson   @ref Backend
717a982d89SJeremy L. Thompson **/
72a681ae63Sjeremylt int CeedElemRestrictionGetStrides(CeedElemRestriction rstr,
73a681ae63Sjeremylt                                   CeedInt (*strides)[3]) {
74a681ae63Sjeremylt   if (!rstr->strides)
75a681ae63Sjeremylt     // LCOV_EXCL_START
76e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_MINOR,
77e15f9bd0SJeremy L Thompson                      "ElemRestriction has no stride data");
78a681ae63Sjeremylt   // LCOV_EXCL_STOP
79a681ae63Sjeremylt 
8092ae7e47SJeremy L Thompson   for (CeedInt i=0; i<3; i++)
81a681ae63Sjeremylt     (*strides)[i] = rstr->strides[i];
82e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
837a982d89SJeremy L. Thompson }
847a982d89SJeremy L. Thompson 
857a982d89SJeremy L. Thompson /**
86bd33150aSjeremylt   @brief Get read-only access to a CeedElemRestriction offsets array by memtype
87bd33150aSjeremylt 
88bd33150aSjeremylt   @param rstr          CeedElemRestriction to retrieve offsets
89d1d35e2fSjeremylt   @param mem_type      Memory type on which to access the array.  If the backend
90bd33150aSjeremylt                          uses a different memory type, this will perform a copy
91bd33150aSjeremylt                          (possibly cached).
92d1d35e2fSjeremylt   @param[out] offsets  Array on memory type mem_type
93bd33150aSjeremylt 
94bd33150aSjeremylt   @return An error code: 0 - success, otherwise - failure
95bd33150aSjeremylt 
96bd33150aSjeremylt   @ref User
97bd33150aSjeremylt **/
98d1d35e2fSjeremylt int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr,
99d1d35e2fSjeremylt                                   CeedMemType mem_type,
100bd33150aSjeremylt                                   const CeedInt **offsets) {
101bd33150aSjeremylt   int ierr;
102bd33150aSjeremylt 
103bd33150aSjeremylt   if (!rstr->GetOffsets)
104bd33150aSjeremylt     // LCOV_EXCL_START
105e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_UNSUPPORTED,
106e15f9bd0SJeremy L Thompson                      "Backend does not support GetOffsets");
107bd33150aSjeremylt   // LCOV_EXCL_STOP
108bd33150aSjeremylt 
109d1d35e2fSjeremylt   ierr = rstr->GetOffsets(rstr, mem_type, offsets); CeedChk(ierr);
110d1d35e2fSjeremylt   rstr->num_readers++;
111e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
112430758c8SJeremy L Thompson }
113430758c8SJeremy L Thompson 
114430758c8SJeremy L Thompson /**
115430758c8SJeremy L Thompson   @brief Restore an offsets array obtained using CeedElemRestrictionGetOffsets()
116430758c8SJeremy L Thompson 
117430758c8SJeremy L Thompson   @param rstr     CeedElemRestriction to restore
118430758c8SJeremy L Thompson   @param offsets  Array of offset data
119430758c8SJeremy L Thompson 
120430758c8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
121430758c8SJeremy L Thompson 
122430758c8SJeremy L Thompson   @ref User
123430758c8SJeremy L Thompson **/
124430758c8SJeremy L Thompson int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr,
125430758c8SJeremy L Thompson                                       const CeedInt **offsets) {
126430758c8SJeremy L Thompson   *offsets = NULL;
127d1d35e2fSjeremylt   rstr->num_readers--;
128e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
129bd33150aSjeremylt }
130bd33150aSjeremylt 
131bd33150aSjeremylt /**
1323ac43b2cSJeremy L Thompson   @brief Get the strided status of a CeedElemRestriction
1333ac43b2cSJeremy L Thompson 
1343ac43b2cSJeremy L Thompson   @param rstr             CeedElemRestriction
135d1d35e2fSjeremylt   @param[out] is_strided  Variable to store strided status, 1 if strided else 0
1363ac43b2cSJeremy L Thompson 
1373ac43b2cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1383ac43b2cSJeremy L Thompson 
1393ac43b2cSJeremy L Thompson   @ref Backend
1403ac43b2cSJeremy L Thompson **/
141d1d35e2fSjeremylt int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) {
142d1d35e2fSjeremylt   *is_strided = rstr->strides ? true : false;
143e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1443ac43b2cSJeremy L Thompson }
1453ac43b2cSJeremy L Thompson 
1463ac43b2cSJeremy L Thompson /**
147b435c5a6Srezgarshakeri   @brief Get oriented status of a CeedElemRestriction
148b435c5a6Srezgarshakeri 
149b435c5a6Srezgarshakeri   @param rstr             CeedElemRestriction
150b435c5a6Srezgarshakeri   @param[out] is_oriented  Variable to store oriented status, 1 if oriented else 0
151b435c5a6Srezgarshakeri 
152b435c5a6Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
153b435c5a6Srezgarshakeri 
154b435c5a6Srezgarshakeri   @ref Backend
155b435c5a6Srezgarshakeri **/
156b435c5a6Srezgarshakeri int CeedElemRestrictionIsOriented(CeedElemRestriction rstr, bool *is_oriented) {
157b435c5a6Srezgarshakeri   *is_oriented = rstr->is_oriented;
158b435c5a6Srezgarshakeri   return CEED_ERROR_SUCCESS;
159b435c5a6Srezgarshakeri }
160b435c5a6Srezgarshakeri 
161b435c5a6Srezgarshakeri /**
162a681ae63Sjeremylt   @brief Get the backend stride status of a CeedElemRestriction
1637a982d89SJeremy L. Thompson 
1647a982d89SJeremy L. Thompson   @param rstr                      CeedElemRestriction
16596b902e2Sjeremylt   @param[out] has_backend_strides  Variable to store stride status
1667a982d89SJeremy L. Thompson 
1677a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1687a982d89SJeremy L. Thompson 
1697a982d89SJeremy L. Thompson   @ref Backend
1707a982d89SJeremy L. Thompson **/
171fd364f38SJeremy L Thompson int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr,
172d1d35e2fSjeremylt     bool *has_backend_strides) {
173a681ae63Sjeremylt   if (!rstr->strides)
174a681ae63Sjeremylt     // LCOV_EXCL_START
175e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_MINOR,
176e15f9bd0SJeremy L Thompson                      "ElemRestriction has no stride data");
177a681ae63Sjeremylt   // LCOV_EXCL_STOP
1787a982d89SJeremy L. Thompson 
179d1d35e2fSjeremylt   *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) &&
180a681ae63Sjeremylt                           (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
181a681ae63Sjeremylt                           (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
182e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1837a982d89SJeremy L. Thompson }
1847a982d89SJeremy L. Thompson 
1857a982d89SJeremy L. Thompson /**
18649fd234cSJeremy L Thompson 
18749fd234cSJeremy L Thompson   @brief Get the E-vector layout of a CeedElemRestriction
18849fd234cSJeremy L Thompson 
18949fd234cSJeremy L Thompson   @param rstr         CeedElemRestriction
19049fd234cSJeremy L Thompson   @param[out] layout  Variable to store layout array,
19149fd234cSJeremy L Thompson                         stored as [nodes, components, elements].
19249fd234cSJeremy L Thompson                         The data for node i, component j, element k in the
19349fd234cSJeremy L Thompson                         E-vector is given by
19495e93d34SJeremy L Thompson                         i*layout[0] + j*layout[1] + k*layout[2]
19549fd234cSJeremy L Thompson 
19649fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
19749fd234cSJeremy L Thompson 
19849fd234cSJeremy L Thompson   @ref Backend
19949fd234cSJeremy L Thompson **/
20049fd234cSJeremy L Thompson int CeedElemRestrictionGetELayout(CeedElemRestriction rstr,
20149fd234cSJeremy L Thompson                                   CeedInt (*layout)[3]) {
20249fd234cSJeremy L Thompson   if (!rstr->layout[0])
20349fd234cSJeremy L Thompson     // LCOV_EXCL_START
204e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_MINOR,
205e15f9bd0SJeremy L Thompson                      "ElemRestriction has no layout data");
20649fd234cSJeremy L Thompson   // LCOV_EXCL_STOP
20749fd234cSJeremy L Thompson 
20892ae7e47SJeremy L Thompson   for (CeedInt i=0; i<3; i++)
20949fd234cSJeremy L Thompson     (*layout)[i] = rstr->layout[i];
210e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
21149fd234cSJeremy L Thompson }
21249fd234cSJeremy L Thompson 
21349fd234cSJeremy L Thompson /**
21449fd234cSJeremy L Thompson 
21549fd234cSJeremy L Thompson   @brief Set the E-vector layout of a CeedElemRestriction
21649fd234cSJeremy L Thompson 
21749fd234cSJeremy L Thompson   @param rstr    CeedElemRestriction
21849fd234cSJeremy L Thompson   @param layout  Variable to containing layout array,
21949fd234cSJeremy L Thompson                    stored as [nodes, components, elements].
22049fd234cSJeremy L Thompson                    The data for node i, component j, element k in the
22149fd234cSJeremy L Thompson                    E-vector is given by
22295e93d34SJeremy L Thompson                    i*layout[0] + j*layout[1] + k*layout[2]
22349fd234cSJeremy L Thompson 
22449fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
22549fd234cSJeremy L Thompson 
22649fd234cSJeremy L Thompson   @ref Backend
22749fd234cSJeremy L Thompson **/
22849fd234cSJeremy L Thompson int CeedElemRestrictionSetELayout(CeedElemRestriction rstr,
22949fd234cSJeremy L Thompson                                   CeedInt layout[3]) {
23092ae7e47SJeremy L Thompson   for (CeedInt i = 0; i<3; i++)
23149fd234cSJeremy L Thompson     rstr->layout[i] = layout[i];
232e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
23349fd234cSJeremy L Thompson }
23449fd234cSJeremy L Thompson 
23549fd234cSJeremy L Thompson /**
2367a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedElemRestriction
2377a982d89SJeremy L. Thompson 
2387a982d89SJeremy L. Thompson   @param rstr       CeedElemRestriction
2397a982d89SJeremy L. Thompson   @param[out] data  Variable to store data
2407a982d89SJeremy L. Thompson 
2417a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2427a982d89SJeremy L. Thompson 
2437a982d89SJeremy L. Thompson   @ref Backend
2447a982d89SJeremy L. Thompson **/
245777ff853SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) {
246777ff853SJeremy L Thompson   *(void **)data = rstr->data;
247e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2487a982d89SJeremy L. Thompson }
2497a982d89SJeremy L. Thompson 
2507a982d89SJeremy L. Thompson /**
2517a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedElemRestriction
2527a982d89SJeremy L. Thompson 
2537a982d89SJeremy L. Thompson   @param[out] rstr  CeedElemRestriction
2547a982d89SJeremy L. Thompson   @param data       Data to set
2557a982d89SJeremy L. Thompson 
2567a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2577a982d89SJeremy L. Thompson 
2587a982d89SJeremy L. Thompson   @ref Backend
2597a982d89SJeremy L. Thompson **/
260777ff853SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) {
261777ff853SJeremy L Thompson   rstr->data = data;
262e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2637a982d89SJeremy L. Thompson }
2647a982d89SJeremy L. Thompson 
26534359f16Sjeremylt /**
26634359f16Sjeremylt   @brief Increment the reference counter for a CeedElemRestriction
26734359f16Sjeremylt 
26834359f16Sjeremylt   @param rstr  ElemRestriction to increment the reference counter
26934359f16Sjeremylt 
27034359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
27134359f16Sjeremylt 
27234359f16Sjeremylt   @ref Backend
27334359f16Sjeremylt **/
2749560d06aSjeremylt int CeedElemRestrictionReference(CeedElemRestriction rstr) {
27534359f16Sjeremylt   rstr->ref_count++;
27634359f16Sjeremylt   return CEED_ERROR_SUCCESS;
27734359f16Sjeremylt }
27834359f16Sjeremylt 
2796e15d496SJeremy L Thompson /**
2806e15d496SJeremy L Thompson   @brief Estimate number of FLOPs required to apply CeedElemRestriction in t_mode
2816e15d496SJeremy L Thompson 
2826e15d496SJeremy L Thompson   @param rstr   ElemRestriction to estimate FLOPs for
2836e15d496SJeremy L Thompson   @param t_mode Apply restriction or transpose
2846e15d496SJeremy L Thompson   @param flops  Address of variable to hold FLOPs estimate
2856e15d496SJeremy L Thompson 
2866e15d496SJeremy L Thompson   @ref Backend
2876e15d496SJeremy L Thompson **/
2886e15d496SJeremy L Thompson int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr,
2899d36ca50SJeremy L Thompson                                         CeedTransposeMode t_mode, CeedSize *flops) {
2906e15d496SJeremy L Thompson   int ierr;
2916e15d496SJeremy L Thompson   bool is_oriented;
2926e15d496SJeremy L Thompson   CeedInt e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size *
2936e15d496SJeremy L Thompson                    rstr->num_comp,
2946e15d496SJeremy L Thompson                    scale = 0;
2956e15d496SJeremy L Thompson 
2966e15d496SJeremy L Thompson   ierr = CeedElemRestrictionIsOriented(rstr, &is_oriented); CeedChk(ierr);
2976e15d496SJeremy L Thompson   switch (t_mode) {
2986e15d496SJeremy L Thompson   case CEED_NOTRANSPOSE: scale = is_oriented ? 1 : 0; break;
2996e15d496SJeremy L Thompson   case CEED_TRANSPOSE:   scale = is_oriented ? 2 : 1; break;
3006e15d496SJeremy L Thompson   }
3016e15d496SJeremy L Thompson   *flops = e_size * scale;
3026e15d496SJeremy L Thompson 
3036e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3046e15d496SJeremy L Thompson }
3056e15d496SJeremy L Thompson 
3067a982d89SJeremy L. Thompson /// @}
3077a982d89SJeremy L. Thompson 
30815910d16Sjeremylt /// @cond DOXYGEN_SKIP
30915910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
31015910d16Sjeremylt /// @endcond
31115910d16Sjeremylt 
3127a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
3137a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
3147a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
3157a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
316d7b241e6Sjeremylt /// @{
317d7b241e6Sjeremylt 
3187a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
31945f1e315Sjeremylt const CeedInt CEED_STRIDES_BACKEND[3] = {0};
3207a982d89SJeremy L. Thompson 
3214cc79fe7SJed Brown /// Indicate that no CeedElemRestriction is provided by the user
3227a982d89SJeremy L. Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE =
3237a982d89SJeremy L. Thompson   &ceed_elemrestriction_none;
3247a982d89SJeremy L. Thompson 
325d7b241e6Sjeremylt /**
326b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
327d7b241e6Sjeremylt 
328b11c1e72Sjeremylt   @param ceed         A Ceed object where the CeedElemRestriction will be created
329d1d35e2fSjeremylt   @param num_elem     Number of elements described in the @a offsets array
330d1d35e2fSjeremylt   @param elem_size    Size (number of "nodes") per element
331d1d35e2fSjeremylt   @param num_comp     Number of field components per interpolation node
33295bb1877Svaleriabarra                         (1 for scalar fields)
333d1d35e2fSjeremylt   @param comp_stride  Stride between components for the same L-vector "node".
33495e93d34SJeremy L Thompson                         Data for node i, component j, element k can be found in
33595e93d34SJeremy L Thompson                         the L-vector at index
336d1d35e2fSjeremylt                         offsets[i + k*elem_size] + j*comp_stride.
337d1d35e2fSjeremylt   @param l_size       The size of the L-vector. This vector may be larger than
338d979a051Sjeremylt                         the elements and fields given by this restriction.
339d1d35e2fSjeremylt   @param mem_type     Memory type of the @a offsets array, see CeedMemType
340d1d35e2fSjeremylt   @param copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
341d1d35e2fSjeremylt   @param offsets      Array of shape [@a num_elem, @a elem_size]. Row i holds the
342d979a051Sjeremylt                         ordered list of the offsets (into the input CeedVector)
3438795c945Sjeremylt                         for the unknowns corresponding to element i, where
344d1d35e2fSjeremylt                         0 <= i < @a num_elem. All offsets must be in the range
345d1d35e2fSjeremylt                         [0, @a l_size - 1].
3464ce2993fSjeremylt   @param[out] rstr    Address of the variable where the newly created
347b11c1e72Sjeremylt                         CeedElemRestriction will be stored
348d7b241e6Sjeremylt 
349b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
350dfdf5a53Sjeremylt 
3517a982d89SJeremy L. Thompson   @ref User
352b11c1e72Sjeremylt **/
353d1d35e2fSjeremylt int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size,
354d1d35e2fSjeremylt                               CeedInt num_comp, CeedInt comp_stride,
355e79b91d9SJeremy L Thompson                               CeedSize l_size, CeedMemType mem_type,
356d1d35e2fSjeremylt                               CeedCopyMode copy_mode, const CeedInt *offsets,
3574ce2993fSjeremylt                               CeedElemRestriction *rstr) {
358d7b241e6Sjeremylt   int ierr;
359d7b241e6Sjeremylt 
3605fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
3615fe0d4faSjeremylt     Ceed delegate;
362aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
363aefd8378Sjeremylt     CeedChk(ierr);
3645fe0d4faSjeremylt 
3655fe0d4faSjeremylt     if (!delegate)
366c042f62fSJeremy L Thompson       // LCOV_EXCL_START
367e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
368e15f9bd0SJeremy L Thompson                        "Backend does not support ElemRestrictionCreate");
369c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
3705fe0d4faSjeremylt 
371d1d35e2fSjeremylt     ierr = CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp,
372d1d35e2fSjeremylt                                      comp_stride, l_size, mem_type, copy_mode,
373d979a051Sjeremylt                                      offsets, rstr); CeedChk(ierr);
374e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
3755fe0d4faSjeremylt   }
3765fe0d4faSjeremylt 
377e022e1f8SJeremy L Thompson   if (elem_size < 1)
378e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
379e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
380e022e1f8SJeremy L Thompson                      "Element size must be at least 1");
381e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
382e022e1f8SJeremy L Thompson 
383e022e1f8SJeremy L Thompson   if (num_comp < 1)
384e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
385e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
386e022e1f8SJeremy L Thompson                      "ElemRestriction must have at least 1 component");
387e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
388e022e1f8SJeremy L Thompson 
3896838cee0SJeremy L Thompson   if (num_comp > 1 && comp_stride < 1)
390e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
391e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
392e022e1f8SJeremy L Thompson                      "ElemRestriction component stride must be at least 1");
393e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
394e022e1f8SJeremy L Thompson 
3954ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
3964ce2993fSjeremylt   (*rstr)->ceed = ceed;
3979560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
398d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
399d1d35e2fSjeremylt   (*rstr)->num_elem = num_elem;
400d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
401d1d35e2fSjeremylt   (*rstr)->num_comp = num_comp;
402d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
403d1d35e2fSjeremylt   (*rstr)->l_size = l_size;
404d1d35e2fSjeremylt   (*rstr)->num_blk = num_elem;
405d1d35e2fSjeremylt   (*rstr)->blk_size = 1;
406b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 0;
407d1d35e2fSjeremylt   ierr = ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, *rstr);
408d979a051Sjeremylt   CeedChk(ierr);
409e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
410d7b241e6Sjeremylt }
411d7b241e6Sjeremylt 
412d7b241e6Sjeremylt /**
413fc0567d9Srezgarshakeri   @brief Create a CeedElemRestriction with orientation sign
414fc0567d9Srezgarshakeri 
415fc0567d9Srezgarshakeri   @param ceed         A Ceed object where the CeedElemRestriction will be created
416fc0567d9Srezgarshakeri   @param num_elem     Number of elements described in the @a offsets array
417fc0567d9Srezgarshakeri   @param elem_size    Size (number of "nodes") per element
418fc0567d9Srezgarshakeri   @param num_comp     Number of field components per interpolation node
419fc0567d9Srezgarshakeri                         (1 for scalar fields)
420fc0567d9Srezgarshakeri   @param comp_stride  Stride between components for the same L-vector "node".
421fc0567d9Srezgarshakeri                         Data for node i, component j, element k can be found in
422fc0567d9Srezgarshakeri                         the L-vector at index
423fc0567d9Srezgarshakeri                         offsets[i + k*elem_size] + j*comp_stride.
424fc0567d9Srezgarshakeri   @param l_size       The size of the L-vector. This vector may be larger than
425fc0567d9Srezgarshakeri                         the elements and fields given by this restriction.
426fc0567d9Srezgarshakeri   @param mem_type     Memory type of the @a offsets array, see CeedMemType
427fc0567d9Srezgarshakeri   @param copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
428fc0567d9Srezgarshakeri   @param offsets      Array of shape [@a num_elem, @a elem_size]. Row i holds the
429fc0567d9Srezgarshakeri                         ordered list of the offsets (into the input CeedVector)
430fc0567d9Srezgarshakeri                         for the unknowns corresponding to element i, where
431fc0567d9Srezgarshakeri                         0 <= i < @a num_elem. All offsets must be in the range
432fc0567d9Srezgarshakeri                         [0, @a l_size - 1].
433fc0567d9Srezgarshakeri   @param orient       Array of shape [@a num_elem, @a elem_size] with bool false
434fc0567d9Srezgarshakeri                         for positively oriented and true to flip the orientation.
435fc0567d9Srezgarshakeri   @param[out] rstr    Address of the variable where the newly created
436fc0567d9Srezgarshakeri                         CeedElemRestriction will be stored
437fc0567d9Srezgarshakeri 
438fc0567d9Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
439fc0567d9Srezgarshakeri 
440fc0567d9Srezgarshakeri   @ref User
441fc0567d9Srezgarshakeri **/
442fc0567d9Srezgarshakeri int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem,
443fc0567d9Srezgarshakeri                                       CeedInt elem_size, CeedInt num_comp,
444e79b91d9SJeremy L Thompson                                       CeedInt comp_stride, CeedSize l_size,
445fc0567d9Srezgarshakeri                                       CeedMemType mem_type, CeedCopyMode copy_mode,
446fc0567d9Srezgarshakeri                                       const CeedInt *offsets, const bool *orient,
447fc0567d9Srezgarshakeri                                       CeedElemRestriction *rstr) {
448fc0567d9Srezgarshakeri   int ierr;
449fc0567d9Srezgarshakeri 
450c7745053SRezgar Shakeri   if (!ceed->ElemRestrictionCreateOriented) {
451fc0567d9Srezgarshakeri     Ceed delegate;
452fc0567d9Srezgarshakeri     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
453fc0567d9Srezgarshakeri     CeedChk(ierr);
454fc0567d9Srezgarshakeri 
455fc0567d9Srezgarshakeri     if (!delegate)
456fc0567d9Srezgarshakeri       // LCOV_EXCL_START
457fc0567d9Srezgarshakeri       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
45861e7462cSRezgar Shakeri                        "Backend does not implement ElemRestrictionCreateOriented");
459fc0567d9Srezgarshakeri     // LCOV_EXCL_STOP
460fc0567d9Srezgarshakeri 
461fc0567d9Srezgarshakeri     ierr = CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size,
462c7745053SRezgar Shakeri            num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
4634dd06d33Srezgarshakeri            orient, rstr); CeedChk(ierr);
464fc0567d9Srezgarshakeri     return CEED_ERROR_SUCCESS;
465fc0567d9Srezgarshakeri   }
466fc0567d9Srezgarshakeri 
467e022e1f8SJeremy L Thompson   if (elem_size < 1)
468e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
469e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
470e022e1f8SJeremy L Thompson                      "Element size must be at least 1");
471e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
472e022e1f8SJeremy L Thompson 
473e022e1f8SJeremy L Thompson   if (num_comp < 1)
474e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
475e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
476e022e1f8SJeremy L Thompson                      "ElemRestriction must have at least 1 component");
477e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
478e022e1f8SJeremy L Thompson 
4796838cee0SJeremy L Thompson   if (num_comp > 1 && comp_stride < 1)
480e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
481e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
482e022e1f8SJeremy L Thompson                      "ElemRestriction component stride must be at least 1");
483e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
484e022e1f8SJeremy L Thompson 
485fc0567d9Srezgarshakeri   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
486fc0567d9Srezgarshakeri   (*rstr)->ceed = ceed;
487fc0567d9Srezgarshakeri   ierr = CeedReference(ceed); CeedChk(ierr);
488fc0567d9Srezgarshakeri   (*rstr)->ref_count = 1;
489fc0567d9Srezgarshakeri   (*rstr)->num_elem = num_elem;
490fc0567d9Srezgarshakeri   (*rstr)->elem_size = elem_size;
491fc0567d9Srezgarshakeri   (*rstr)->num_comp = num_comp;
492fc0567d9Srezgarshakeri   (*rstr)->comp_stride = comp_stride;
493fc0567d9Srezgarshakeri   (*rstr)->l_size = l_size;
494fc0567d9Srezgarshakeri   (*rstr)->num_blk = num_elem;
495fc0567d9Srezgarshakeri   (*rstr)->blk_size = 1;
496b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 1;
4974dd06d33Srezgarshakeri   ierr = ceed->ElemRestrictionCreateOriented(mem_type, copy_mode,
4984dd06d33Srezgarshakeri          offsets, orient, *rstr); CeedChk(ierr);
499fc0567d9Srezgarshakeri   return CEED_ERROR_SUCCESS;
500fc0567d9Srezgarshakeri }
501fc0567d9Srezgarshakeri 
502fc0567d9Srezgarshakeri /**
5037509a596Sjeremylt   @brief Create a strided CeedElemRestriction
504d7b241e6Sjeremylt 
505b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
506d1d35e2fSjeremylt   @param num_elem   Number of elements described by the restriction
507d1d35e2fSjeremylt   @param elem_size  Size (number of "nodes") per element
508d1d35e2fSjeremylt   @param num_comp   Number of field components per interpolation "node"
50995bb1877Svaleriabarra                       (1 for scalar fields)
510d1d35e2fSjeremylt   @param l_size     The size of the L-vector. This vector may be larger than
511d979a051Sjeremylt                       the elements and fields given by this restriction.
5127509a596Sjeremylt   @param strides    Array for strides between [nodes, components, elements].
51395e93d34SJeremy L Thompson                       Data for node i, component j, element k can be found in
51495e93d34SJeremy L Thompson                       the L-vector at index
51595e93d34SJeremy L Thompson                       i*strides[0] + j*strides[1] + k*strides[2].
51695e93d34SJeremy L Thompson                       @a CEED_STRIDES_BACKEND may be used with vectors created
51795e93d34SJeremy L Thompson                       by a Ceed backend.
5184ce2993fSjeremylt   @param rstr       Address of the variable where the newly created
519b11c1e72Sjeremylt                       CeedElemRestriction will be stored
520d7b241e6Sjeremylt 
521b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
522dfdf5a53Sjeremylt 
5237a982d89SJeremy L. Thompson   @ref User
524b11c1e72Sjeremylt **/
525d1d35e2fSjeremylt int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem,
526d1d35e2fSjeremylt                                      CeedInt elem_size,
527e79b91d9SJeremy L Thompson                                      CeedInt num_comp, CeedSize l_size,
5288621c6c6SJeremy L Thompson                                      const CeedInt strides[3],
529f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
530d7b241e6Sjeremylt   int ierr;
531d7b241e6Sjeremylt 
5325fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
5335fe0d4faSjeremylt     Ceed delegate;
534aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
535aefd8378Sjeremylt     CeedChk(ierr);
5365fe0d4faSjeremylt 
5375fe0d4faSjeremylt     if (!delegate)
538c042f62fSJeremy L Thompson       // LCOV_EXCL_START
539e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
540e15f9bd0SJeremy L Thompson                        "Backend does not support ElemRestrictionCreate");
541c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
5425fe0d4faSjeremylt 
543d1d35e2fSjeremylt     ierr = CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp,
544d1d35e2fSjeremylt                                             l_size, strides, rstr);
545d979a051Sjeremylt     CeedChk(ierr);
546e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
5475fe0d4faSjeremylt   }
5485fe0d4faSjeremylt 
549e022e1f8SJeremy L Thompson   if (elem_size < 1)
550e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
551e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
552e022e1f8SJeremy L Thompson                      "Element size must be at least 1");
553e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
554e022e1f8SJeremy L Thompson 
555e022e1f8SJeremy L Thompson   if (num_comp < 1)
556e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
557e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
558e022e1f8SJeremy L Thompson                      "ElemRestriction must have at least 1 component");
559e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
560e022e1f8SJeremy L Thompson 
5614ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
5624ce2993fSjeremylt   (*rstr)->ceed = ceed;
5639560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
564d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
565d1d35e2fSjeremylt   (*rstr)->num_elem = num_elem;
566d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
567d1d35e2fSjeremylt   (*rstr)->num_comp = num_comp;
568d1d35e2fSjeremylt   (*rstr)->l_size = l_size;
569d1d35e2fSjeremylt   (*rstr)->num_blk = num_elem;
570d1d35e2fSjeremylt   (*rstr)->blk_size = 1;
571b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 0;
5727509a596Sjeremylt   ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr);
57392ae7e47SJeremy L Thompson   for (CeedInt i=0; i<3; i++)
5747509a596Sjeremylt     (*rstr)->strides[i] = strides[i];
5751dfeef1dSjeremylt   ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL,
5761dfeef1dSjeremylt                                      *rstr);
5774b8bea3bSJed Brown   CeedChk(ierr);
578e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
579d7b241e6Sjeremylt }
580d7b241e6Sjeremylt 
581d7b241e6Sjeremylt /**
582b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
583d7b241e6Sjeremylt 
584d7b241e6Sjeremylt   @param ceed         A Ceed object where the CeedElemRestriction will be created.
585d1d35e2fSjeremylt   @param num_elem     Number of elements described in the @a offsets array.
586d1d35e2fSjeremylt   @param elem_size    Size (number of unknowns) per element
587d1d35e2fSjeremylt   @param blk_size     Number of elements in a block
588d1d35e2fSjeremylt   @param num_comp     Number of field components per interpolation node
58995bb1877Svaleriabarra                         (1 for scalar fields)
590d1d35e2fSjeremylt   @param comp_stride  Stride between components for the same L-vector "node".
59195e93d34SJeremy L Thompson                         Data for node i, component j, element k can be found in
59295e93d34SJeremy L Thompson                         the L-vector at index
593d1d35e2fSjeremylt                         offsets[i + k*elem_size] + j*comp_stride.
594d1d35e2fSjeremylt   @param l_size       The size of the L-vector. This vector may be larger than
595d979a051Sjeremylt                         the elements and fields given by this restriction.
596d1d35e2fSjeremylt   @param mem_type     Memory type of the @a offsets array, see CeedMemType
597d1d35e2fSjeremylt   @param copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
598d1d35e2fSjeremylt   @param offsets      Array of shape [@a num_elem, @a elem_size]. Row i holds the
599d979a051Sjeremylt                         ordered list of the offsets (into the input CeedVector)
6008795c945Sjeremylt                         for the unknowns corresponding to element i, where
601d1d35e2fSjeremylt                         0 <= i < @a num_elem. All offsets must be in the range
602d1d35e2fSjeremylt                         [0, @a l_size - 1]. The backend will permute and pad this
6038795c945Sjeremylt                         array to the desired ordering for the blocksize, which is
6048795c945Sjeremylt                         typically given by the backend. The default reordering is
6058795c945Sjeremylt                         to interlace elements.
6064ce2993fSjeremylt   @param rstr         Address of the variable where the newly created
607b11c1e72Sjeremylt                         CeedElemRestriction will be stored
608d7b241e6Sjeremylt 
609b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
610dfdf5a53Sjeremylt 
6117a982d89SJeremy L. Thompson   @ref Backend
612b11c1e72Sjeremylt  **/
613d1d35e2fSjeremylt int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem,
614d1d35e2fSjeremylt                                      CeedInt elem_size,
615d1d35e2fSjeremylt                                      CeedInt blk_size, CeedInt num_comp,
616e79b91d9SJeremy L Thompson                                      CeedInt comp_stride, CeedSize l_size,
617d1d35e2fSjeremylt                                      CeedMemType mem_type, CeedCopyMode copy_mode,
618d979a051Sjeremylt                                      const CeedInt *offsets,
6194ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
620d7b241e6Sjeremylt   int ierr;
621d1d35e2fSjeremylt   CeedInt *blk_offsets;
622d1d35e2fSjeremylt   CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
623d7b241e6Sjeremylt 
6245fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
6255fe0d4faSjeremylt     Ceed delegate;
626aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
627aefd8378Sjeremylt     CeedChk(ierr);
6285fe0d4faSjeremylt 
6295fe0d4faSjeremylt     if (!delegate)
630c042f62fSJeremy L Thompson       // LCOV_EXCL_START
631e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support "
6321d102b48SJeremy L Thompson                        "ElemRestrictionCreateBlocked");
633c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
6345fe0d4faSjeremylt 
635d1d35e2fSjeremylt     ierr = CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, blk_size,
636d1d35e2fSjeremylt                                             num_comp, comp_stride, l_size, mem_type,
637d1d35e2fSjeremylt                                             copy_mode, offsets, rstr);
638d979a051Sjeremylt     CeedChk(ierr);
639e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6405fe0d4faSjeremylt   }
641d7b241e6Sjeremylt 
642e022e1f8SJeremy L Thompson   if (elem_size < 1)
643e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
644e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
645e022e1f8SJeremy L Thompson                      "Element size must be at least 1");
646e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
647e022e1f8SJeremy L Thompson 
648e022e1f8SJeremy L Thompson   if (blk_size < 1)
649e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
650e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
651e022e1f8SJeremy L Thompson                      "Block size must be at least 1");
652e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
653e022e1f8SJeremy L Thompson 
654e022e1f8SJeremy L Thompson   if (num_comp < 1)
655e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
656e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
657e022e1f8SJeremy L Thompson                      "ElemRestriction must have at least 1 component");
658e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
659e022e1f8SJeremy L Thompson 
6606838cee0SJeremy L Thompson   if (num_comp > 1 && comp_stride < 1)
661e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
662e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
663e022e1f8SJeremy L Thompson                      "ElemRestriction component stride must be at least 1");
664e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
665e022e1f8SJeremy L Thompson 
6664ce2993fSjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
667d7b241e6Sjeremylt 
668d1d35e2fSjeremylt   ierr = CeedCalloc(num_blk*blk_size*elem_size, &blk_offsets); CeedChk(ierr);
669d1d35e2fSjeremylt   ierr = CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size,
670d1d35e2fSjeremylt                                elem_size); CeedChk(ierr);
671d7b241e6Sjeremylt 
6724ce2993fSjeremylt   (*rstr)->ceed = ceed;
6739560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
674d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
675d1d35e2fSjeremylt   (*rstr)->num_elem = num_elem;
676d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
677d1d35e2fSjeremylt   (*rstr)->num_comp = num_comp;
678d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
679d1d35e2fSjeremylt   (*rstr)->l_size = l_size;
680d1d35e2fSjeremylt   (*rstr)->num_blk = num_blk;
681d1d35e2fSjeremylt   (*rstr)->blk_size = blk_size;
682b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 0;
683667bc5fcSjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
684d1d35e2fSjeremylt          (const CeedInt *) blk_offsets, *rstr); CeedChk(ierr);
685d1d35e2fSjeremylt   if (copy_mode == CEED_OWN_POINTER) {
686d979a051Sjeremylt     ierr = CeedFree(&offsets); CeedChk(ierr);
6871d102b48SJeremy L Thompson   }
688e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
689d7b241e6Sjeremylt }
690d7b241e6Sjeremylt 
691b11c1e72Sjeremylt /**
6927509a596Sjeremylt   @brief Create a blocked strided CeedElemRestriction
6937509a596Sjeremylt 
6947509a596Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
695d1d35e2fSjeremylt   @param num_elem   Number of elements described by the restriction
696d1d35e2fSjeremylt   @param elem_size  Size (number of "nodes") per element
697d1d35e2fSjeremylt   @param blk_size   Number of elements in a block
698d1d35e2fSjeremylt   @param num_comp   Number of field components per interpolation node
6997509a596Sjeremylt                       (1 for scalar fields)
700d1d35e2fSjeremylt   @param l_size     The size of the L-vector. This vector may be larger than
701d979a051Sjeremylt                       the elements and fields given by this restriction.
7027509a596Sjeremylt   @param strides    Array for strides between [nodes, components, elements].
70395e93d34SJeremy L Thompson                       Data for node i, component j, element k can be found in
70495e93d34SJeremy L Thompson                       the L-vector at index
70595e93d34SJeremy L Thompson                       i*strides[0] + j*strides[1] + k*strides[2].
70695e93d34SJeremy L Thompson                       @a CEED_STRIDES_BACKEND may be used with vectors created
70795e93d34SJeremy L Thompson                       by a Ceed backend.
7087509a596Sjeremylt   @param rstr       Address of the variable where the newly created
7097509a596Sjeremylt                       CeedElemRestriction will be stored
7107509a596Sjeremylt 
7117509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
7127509a596Sjeremylt 
7137a982d89SJeremy L. Thompson   @ref User
7147509a596Sjeremylt **/
715d1d35e2fSjeremylt int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem,
716e79b91d9SJeremy L Thompson     CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedSize l_size,
7178621c6c6SJeremy L Thompson     const CeedInt strides[3], CeedElemRestriction *rstr) {
7187509a596Sjeremylt   int ierr;
719d1d35e2fSjeremylt   CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
7207509a596Sjeremylt 
7217509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
7227509a596Sjeremylt     Ceed delegate;
7237509a596Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
7247509a596Sjeremylt     CeedChk(ierr);
7257509a596Sjeremylt 
7267509a596Sjeremylt     if (!delegate)
7277509a596Sjeremylt       // LCOV_EXCL_START
728e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support "
7297509a596Sjeremylt                        "ElemRestrictionCreateBlocked");
7307509a596Sjeremylt     // LCOV_EXCL_STOP
7317509a596Sjeremylt 
732d1d35e2fSjeremylt     ierr = CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size,
733d1d35e2fSjeremylt            blk_size, num_comp, l_size, strides, rstr); CeedChk(ierr);
734e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
7357509a596Sjeremylt   }
7367509a596Sjeremylt 
737e022e1f8SJeremy L Thompson   if (elem_size < 1)
738e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
739e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
740e022e1f8SJeremy L Thompson                      "Element size must be at least 1");
741e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
742e022e1f8SJeremy L Thompson 
743e022e1f8SJeremy L Thompson   if (blk_size < 1)
744e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
745e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
746e022e1f8SJeremy L Thompson                      "Block size must be at least 1");
747e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
748e022e1f8SJeremy L Thompson 
749e022e1f8SJeremy L Thompson   if (num_comp < 1)
750e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
751e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
752e022e1f8SJeremy L Thompson                      "ElemRestriction must have at least 1 component");
753e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
754e022e1f8SJeremy L Thompson 
7557509a596Sjeremylt   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
7567509a596Sjeremylt 
7577509a596Sjeremylt   (*rstr)->ceed = ceed;
7589560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
759d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
760d1d35e2fSjeremylt   (*rstr)->num_elem = num_elem;
761d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
762d1d35e2fSjeremylt   (*rstr)->num_comp = num_comp;
763d1d35e2fSjeremylt   (*rstr)->l_size = l_size;
764d1d35e2fSjeremylt   (*rstr)->num_blk = num_blk;
765d1d35e2fSjeremylt   (*rstr)->blk_size = blk_size;
766b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 0;
7677509a596Sjeremylt   ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr);
76892ae7e47SJeremy L Thompson   for (CeedInt i=0; i<3; i++)
7697509a596Sjeremylt     (*rstr)->strides[i] = strides[i];
7707509a596Sjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
7717509a596Sjeremylt          NULL, *rstr); CeedChk(ierr);
772e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
7737509a596Sjeremylt }
7747509a596Sjeremylt 
7757509a596Sjeremylt /**
7769560d06aSjeremylt   @brief Copy the pointer to a CeedElemRestriction. Both pointers should
7779560d06aSjeremylt            be destroyed with `CeedElemRestrictionDestroy()`;
7789560d06aSjeremylt            Note: If `*rstr_copy` is non-NULL, then it is assumed that
7799560d06aSjeremylt            `*rstr_copy` is a pointer to a CeedElemRestriction. This
7809560d06aSjeremylt            CeedElemRestriction will be destroyed if `*rstr_copy` is the
7819560d06aSjeremylt            only reference to this CeedElemRestriction.
7829560d06aSjeremylt 
7839560d06aSjeremylt   @param rstr            CeedElemRestriction to copy reference to
7849560d06aSjeremylt   @param[out] rstr_copy  Variable to store copied reference
7859560d06aSjeremylt 
7869560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
7879560d06aSjeremylt 
7889560d06aSjeremylt   @ref User
7899560d06aSjeremylt **/
7909560d06aSjeremylt int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr,
7919560d06aSjeremylt                                      CeedElemRestriction *rstr_copy) {
7929560d06aSjeremylt   int ierr;
7939560d06aSjeremylt 
7949560d06aSjeremylt   ierr = CeedElemRestrictionReference(rstr); CeedChk(ierr);
7959560d06aSjeremylt   ierr = CeedElemRestrictionDestroy(rstr_copy); CeedChk(ierr);
7969560d06aSjeremylt   *rstr_copy = rstr;
7979560d06aSjeremylt   return CEED_ERROR_SUCCESS;
7989560d06aSjeremylt }
7999560d06aSjeremylt 
8009560d06aSjeremylt /**
801b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
802b11c1e72Sjeremylt 
8034ce2993fSjeremylt   @param rstr   CeedElemRestriction
804d1d35e2fSjeremylt   @param l_vec  The address of the L-vector to be created, or NULL
805d1d35e2fSjeremylt   @param e_vec  The address of the E-vector to be created, or NULL
806b11c1e72Sjeremylt 
807b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
808dfdf5a53Sjeremylt 
8097a982d89SJeremy L. Thompson   @ref User
810b11c1e72Sjeremylt **/
811d1d35e2fSjeremylt int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec,
812d1d35e2fSjeremylt                                     CeedVector *e_vec) {
813d7b241e6Sjeremylt   int ierr;
814d2643443SJeremy L Thompson   CeedSize e_size, l_size;
815d1d35e2fSjeremylt   l_size = rstr->l_size;
816d1d35e2fSjeremylt   e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
817d1d35e2fSjeremylt   if (l_vec) {
818d1d35e2fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, l_size, l_vec); CeedChk(ierr);
819d7b241e6Sjeremylt   }
820d1d35e2fSjeremylt   if (e_vec) {
821d1d35e2fSjeremylt     ierr = CeedVectorCreate(rstr->ceed, e_size, e_vec); CeedChk(ierr);
822d7b241e6Sjeremylt   }
823e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
824d7b241e6Sjeremylt }
825d7b241e6Sjeremylt 
826d7b241e6Sjeremylt /**
827d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
828d7b241e6Sjeremylt 
8294ce2993fSjeremylt   @param rstr    CeedElemRestriction
830d1d35e2fSjeremylt   @param t_mode  Apply restriction or transpose
831d1d35e2fSjeremylt   @param u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
832d1d35e2fSjeremylt   @param ru      Output vector (of shape [@a num_elem * @a elem_size] when
833d1d35e2fSjeremylt                    t_mode=@ref CEED_NOTRANSPOSE). Ordering of the e-vector is decided
8347aaeacdcSjeremylt                    by the backend.
8354cc79fe7SJed Brown   @param request Request or @ref CEED_REQUEST_IMMEDIATE
836b11c1e72Sjeremylt 
837b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
838dfdf5a53Sjeremylt 
8397a982d89SJeremy L. Thompson   @ref User
840b11c1e72Sjeremylt **/
841d1d35e2fSjeremylt int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode,
842a8d32208Sjeremylt                              CeedVector u, CeedVector ru,
843a8d32208Sjeremylt                              CeedRequest *request) {
844d7b241e6Sjeremylt   CeedInt m, n;
845d7b241e6Sjeremylt   int ierr;
846d7b241e6Sjeremylt 
847d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
848d1d35e2fSjeremylt     m = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
849d1d35e2fSjeremylt     n = rstr->l_size;
850d7b241e6Sjeremylt   } else {
851d1d35e2fSjeremylt     m = rstr->l_size;
852d1d35e2fSjeremylt     n = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
853d7b241e6Sjeremylt   }
854d7b241e6Sjeremylt   if (n != u->length)
855c042f62fSJeremy L Thompson     // LCOV_EXCL_START
856e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
857e15f9bd0SJeremy L Thompson                      "Input vector size %d not compatible with "
8581d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
859c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
860a8d32208Sjeremylt   if (m != ru->length)
861c042f62fSJeremy L Thompson     // LCOV_EXCL_START
862e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
863e15f9bd0SJeremy L Thompson                      "Output vector size %d not compatible with "
864a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
865c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
866*52b3e6a7SJed Brown   if (rstr->num_elem > 0) {
867d1d35e2fSjeremylt     ierr = rstr->Apply(rstr, t_mode, u, ru, request); CeedChk(ierr);
868*52b3e6a7SJed Brown   }
869e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
870d7b241e6Sjeremylt }
871d7b241e6Sjeremylt 
872d7b241e6Sjeremylt /**
873d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
874be9261b7Sjeremylt 
875be9261b7Sjeremylt   @param rstr    CeedElemRestriction
8761f37b403Sjeremylt   @param block   Block number to restrict to/from, i.e. block=0 will handle
877d1d35e2fSjeremylt                    elements [0 : blk_size] and block=3 will handle elements
878d1d35e2fSjeremylt                    [3*blk_size : 4*blk_size]
879d1d35e2fSjeremylt   @param t_mode  Apply restriction or transpose
880d1d35e2fSjeremylt   @param u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
881d1d35e2fSjeremylt   @param ru      Output vector (of shape [@a blk_size * @a elem_size] when
882d1d35e2fSjeremylt                    t_mode=@ref CEED_NOTRANSPOSE). Ordering of the e-vector is decided
8837aaeacdcSjeremylt                    by the backend.
8844cc79fe7SJed Brown   @param request Request or @ref CEED_REQUEST_IMMEDIATE
885be9261b7Sjeremylt 
886be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
887be9261b7Sjeremylt 
8887a982d89SJeremy L. Thompson   @ref Backend
889be9261b7Sjeremylt **/
890be9261b7Sjeremylt int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block,
891d1d35e2fSjeremylt                                   CeedTransposeMode t_mode, CeedVector u,
892a8d32208Sjeremylt                                   CeedVector ru, CeedRequest *request) {
893be9261b7Sjeremylt   CeedInt m, n;
894be9261b7Sjeremylt   int ierr;
895be9261b7Sjeremylt 
896d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
897d1d35e2fSjeremylt     m = rstr->blk_size * rstr->elem_size * rstr->num_comp;
898d1d35e2fSjeremylt     n = rstr->l_size;
899be9261b7Sjeremylt   } else {
900d1d35e2fSjeremylt     m = rstr->l_size;
901d1d35e2fSjeremylt     n = rstr->blk_size * rstr->elem_size * rstr->num_comp;
902be9261b7Sjeremylt   }
903be9261b7Sjeremylt   if (n != u->length)
904c042f62fSJeremy L Thompson     // LCOV_EXCL_START
905e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
906e15f9bd0SJeremy L Thompson                      "Input vector size %d not compatible with "
9071d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
908c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
909a8d32208Sjeremylt   if (m != ru->length)
910c042f62fSJeremy L Thompson     // LCOV_EXCL_START
911e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
912e15f9bd0SJeremy L Thompson                      "Output vector size %d not compatible with "
913a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
914c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
915d1d35e2fSjeremylt   if (rstr->blk_size*block > rstr->num_elem)
916c042f62fSJeremy L Thompson     // LCOV_EXCL_START
917e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
918e15f9bd0SJeremy L Thompson                      "Cannot retrieve block %d, element %d > "
919d1d35e2fSjeremylt                      "total elements %d", block, rstr->blk_size*block,
920d1d35e2fSjeremylt                      rstr->num_elem);
921c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
922d1d35e2fSjeremylt   ierr = rstr->ApplyBlock(rstr, block, t_mode, u, ru, request);
923be9261b7Sjeremylt   CeedChk(ierr);
924e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
925be9261b7Sjeremylt }
926be9261b7Sjeremylt 
927be9261b7Sjeremylt /**
928b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedElemRestriction
929b7c9bbdaSJeremy L Thompson 
930b7c9bbdaSJeremy L Thompson   @param rstr       CeedElemRestriction
931b7c9bbdaSJeremy L Thompson   @param[out] ceed  Variable to store Ceed
932b7c9bbdaSJeremy L Thompson 
933b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
934b7c9bbdaSJeremy L Thompson 
935b7c9bbdaSJeremy L Thompson   @ref Advanced
936b7c9bbdaSJeremy L Thompson **/
937b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
938b7c9bbdaSJeremy L Thompson   *ceed = rstr->ceed;
939b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
940b7c9bbdaSJeremy L Thompson }
941b7c9bbdaSJeremy L Thompson 
942b7c9bbdaSJeremy L Thompson /**
943d979a051Sjeremylt   @brief Get the L-vector component stride
944a681ae63Sjeremylt 
945a681ae63Sjeremylt   @param rstr              CeedElemRestriction
946d1d35e2fSjeremylt   @param[out] comp_stride  Variable to store component stride
947a681ae63Sjeremylt 
948a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
949a681ae63Sjeremylt 
950b7c9bbdaSJeremy L Thompson   @ref Advanced
951a681ae63Sjeremylt **/
952d979a051Sjeremylt int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr,
953d1d35e2fSjeremylt                                      CeedInt *comp_stride) {
954d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
955e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
956a681ae63Sjeremylt }
957a681ae63Sjeremylt 
958a681ae63Sjeremylt /**
959a681ae63Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
960a681ae63Sjeremylt 
961a681ae63Sjeremylt   @param rstr           CeedElemRestriction
962d1d35e2fSjeremylt   @param[out] num_elem  Variable to store number of elements
963a681ae63Sjeremylt 
964a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
965a681ae63Sjeremylt 
966b7c9bbdaSJeremy L Thompson   @ref Advanced
967a681ae63Sjeremylt **/
968a681ae63Sjeremylt int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
969d1d35e2fSjeremylt                                       CeedInt *num_elem) {
970d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
971e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
972a681ae63Sjeremylt }
973a681ae63Sjeremylt 
974a681ae63Sjeremylt /**
975a681ae63Sjeremylt   @brief Get the size of elements in the CeedElemRestriction
976a681ae63Sjeremylt 
977a681ae63Sjeremylt   @param rstr            CeedElemRestriction
978d1d35e2fSjeremylt   @param[out] elem_size  Variable to store size of elements
979a681ae63Sjeremylt 
980a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
981a681ae63Sjeremylt 
982b7c9bbdaSJeremy L Thompson   @ref Advanced
983a681ae63Sjeremylt **/
984a681ae63Sjeremylt int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
985d1d35e2fSjeremylt                                       CeedInt *elem_size) {
986d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
987e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
988a681ae63Sjeremylt }
989a681ae63Sjeremylt 
990a681ae63Sjeremylt /**
991d979a051Sjeremylt   @brief Get the size of the l-vector for a CeedElemRestriction
992a681ae63Sjeremylt 
993a681ae63Sjeremylt   @param rstr         CeedElemRestriction
994d1d35e2fSjeremylt   @param[out] l_size  Variable to store number of nodes
995a681ae63Sjeremylt 
996a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
997a681ae63Sjeremylt 
998b7c9bbdaSJeremy L Thompson   @ref Advanced
999a681ae63Sjeremylt **/
1000d979a051Sjeremylt int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr,
1001e79b91d9SJeremy L Thompson                                       CeedSize *l_size) {
1002d1d35e2fSjeremylt   *l_size = rstr->l_size;
1003e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1004a681ae63Sjeremylt }
1005a681ae63Sjeremylt 
1006a681ae63Sjeremylt /**
1007a681ae63Sjeremylt   @brief Get the number of components in the elements of a
1008a681ae63Sjeremylt          CeedElemRestriction
1009a681ae63Sjeremylt 
1010a681ae63Sjeremylt   @param rstr           CeedElemRestriction
1011d1d35e2fSjeremylt   @param[out] num_comp  Variable to store number of components
1012a681ae63Sjeremylt 
1013a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1014a681ae63Sjeremylt 
1015b7c9bbdaSJeremy L Thompson   @ref Advanced
1016a681ae63Sjeremylt **/
1017a681ae63Sjeremylt int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
1018d1d35e2fSjeremylt                                         CeedInt *num_comp) {
1019d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
1020e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1021a681ae63Sjeremylt }
1022a681ae63Sjeremylt 
1023a681ae63Sjeremylt /**
1024a681ae63Sjeremylt   @brief Get the number of blocks in a CeedElemRestriction
1025a681ae63Sjeremylt 
1026a681ae63Sjeremylt   @param rstr            CeedElemRestriction
1027d1d35e2fSjeremylt   @param[out] num_block  Variable to store number of blocks
1028a681ae63Sjeremylt 
1029a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1030a681ae63Sjeremylt 
1031b7c9bbdaSJeremy L Thompson   @ref Advanced
1032a681ae63Sjeremylt **/
1033a681ae63Sjeremylt int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
1034d1d35e2fSjeremylt                                     CeedInt *num_block) {
1035d1d35e2fSjeremylt   *num_block = rstr->num_blk;
1036e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1037a681ae63Sjeremylt }
1038a681ae63Sjeremylt 
1039a681ae63Sjeremylt /**
1040a681ae63Sjeremylt   @brief Get the size of blocks in the CeedElemRestriction
1041a681ae63Sjeremylt 
1042a681ae63Sjeremylt   @param rstr           CeedElemRestriction
1043d1d35e2fSjeremylt   @param[out] blk_size  Variable to store size of blocks
1044a681ae63Sjeremylt 
1045a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1046a681ae63Sjeremylt 
1047b7c9bbdaSJeremy L Thompson   @ref Advanced
1048a681ae63Sjeremylt **/
1049a681ae63Sjeremylt int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
1050d1d35e2fSjeremylt                                     CeedInt *blk_size) {
1051d1d35e2fSjeremylt   *blk_size = rstr->blk_size;
1052e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1053a681ae63Sjeremylt }
1054a681ae63Sjeremylt 
1055a681ae63Sjeremylt /**
1056d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
10571469ee4dSjeremylt 
10581469ee4dSjeremylt   @param rstr       CeedElemRestriction
1059d1d35e2fSjeremylt   @param[out] mult  Vector to store multiplicity (of size l_size)
10601469ee4dSjeremylt 
10611469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
10621469ee4dSjeremylt 
10637a982d89SJeremy L. Thompson   @ref User
10641469ee4dSjeremylt **/
10651469ee4dSjeremylt int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr,
10661469ee4dSjeremylt                                        CeedVector mult) {
10671469ee4dSjeremylt   int ierr;
1068d1d35e2fSjeremylt   CeedVector e_vec;
10691469ee4dSjeremylt 
107025509ebbSRezgar Shakeri   // Create e_vec to hold intermediate computation in E^T (E 1)
1071d1d35e2fSjeremylt   ierr = CeedElemRestrictionCreateVector(rstr, NULL, &e_vec); CeedChk(ierr);
10721469ee4dSjeremylt 
107325509ebbSRezgar Shakeri   // Compute e_vec = E * 1
107425509ebbSRezgar Shakeri   ierr = CeedVectorSetValue(mult, 1.0); CeedChk(ierr);
107525509ebbSRezgar Shakeri   ierr = CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec,
107625509ebbSRezgar Shakeri                                   CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
107725509ebbSRezgar Shakeri   // Compute multiplicity, mult = E^T * e_vec = E^T (E 1)
107825509ebbSRezgar Shakeri   ierr = CeedVectorSetValue(mult, 0.0); CeedChk(ierr);
1079d1d35e2fSjeremylt   ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult,
1080efc78312Sjeremylt                                   CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
10811469ee4dSjeremylt   // Cleanup
1082d1d35e2fSjeremylt   ierr = CeedVectorDestroy(&e_vec); CeedChk(ierr);
1083e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
10841469ee4dSjeremylt }
10851469ee4dSjeremylt 
10861469ee4dSjeremylt /**
1087f02ca4a2SJed Brown   @brief View a CeedElemRestriction
1088f02ca4a2SJed Brown 
1089f02ca4a2SJed Brown   @param[in] rstr    CeedElemRestriction to view
1090f02ca4a2SJed Brown   @param[in] stream  Stream to write; typically stdout/stderr or a file
1091f02ca4a2SJed Brown 
1092f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
1093f02ca4a2SJed Brown 
10947a982d89SJeremy L. Thompson   @ref User
1095f02ca4a2SJed Brown **/
1096f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
10977509a596Sjeremylt   char stridesstr[500];
10987509a596Sjeremylt   if (rstr->strides)
10997509a596Sjeremylt     sprintf(stridesstr, "[%d, %d, %d]", rstr->strides[0], rstr->strides[1],
11007509a596Sjeremylt             rstr->strides[2]);
1101d979a051Sjeremylt   else
1102d1d35e2fSjeremylt     sprintf(stridesstr, "%d", rstr->comp_stride);
11037509a596Sjeremylt 
11045b76854bSJeremy L Thompson   fprintf(stream, "%sCeedElemRestriction from (%td, %d) to %d elements with %d "
1105d1d35e2fSjeremylt           "nodes each and %s %s\n", rstr->blk_size > 1 ? "Blocked " : "",
1106d1d35e2fSjeremylt           rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
1107d979a051Sjeremylt           rstr->strides ? "strides" : "component stride", stridesstr);
1108e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1109f02ca4a2SJed Brown }
1110f02ca4a2SJed Brown 
1111f02ca4a2SJed Brown /**
1112b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
1113b11c1e72Sjeremylt 
11144ce2993fSjeremylt   @param rstr  CeedElemRestriction to destroy
1115b11c1e72Sjeremylt 
1116b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1117dfdf5a53Sjeremylt 
11187a982d89SJeremy L. Thompson   @ref User
1119b11c1e72Sjeremylt **/
11204ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
1121d7b241e6Sjeremylt   int ierr;
1122d7b241e6Sjeremylt 
1123d1d35e2fSjeremylt   if (!*rstr || --(*rstr)->ref_count > 0) return CEED_ERROR_SUCCESS;
1124d1d35e2fSjeremylt   if ((*rstr)->num_readers)
11258229195eSjeremylt     // LCOV_EXCL_START
1126e15f9bd0SJeremy L Thompson     return CeedError((*rstr)->ceed, CEED_ERROR_ACCESS,
1127e15f9bd0SJeremy L Thompson                      "Cannot destroy CeedElemRestriction, "
1128430758c8SJeremy L Thompson                      "a process has read access to the offset data");
11298229195eSjeremylt   // LCOV_EXCL_STOP
11304ce2993fSjeremylt   if ((*rstr)->Destroy) {
11314ce2993fSjeremylt     ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr);
1132d7b241e6Sjeremylt   }
11337509a596Sjeremylt   ierr = CeedFree(&(*rstr)->strides); CeedChk(ierr);
11344ce2993fSjeremylt   ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr);
11354ce2993fSjeremylt   ierr = CeedFree(rstr); CeedChk(ierr);
1136e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1137d7b241e6Sjeremylt }
1138d7b241e6Sjeremylt 
1139d7b241e6Sjeremylt /// @}
1140