xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-elemrestriction.c (revision 2b730f8b5a9c809740a0b3b302db43a719c636b1)
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 
83d576824SJeremy L Thompson #include <ceed-impl.h>
9*2b730f8bSJeremy L Thompson #include <ceed/backend.h>
10*2b730f8bSJeremy L Thompson #include <ceed/ceed.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 **/
42*2b730f8bSJeremy L Thompson int CeedPermutePadOffsets(const CeedInt *offsets, CeedInt *blk_offsets, CeedInt num_blk, CeedInt num_elem, CeedInt blk_size, CeedInt elem_size) {
43*2b730f8bSJeremy L Thompson   for (CeedInt e = 0; e < num_blk * blk_size; e += blk_size) {
44*2b730f8bSJeremy L Thompson     for (CeedInt j = 0; j < blk_size; j++) {
45*2b730f8bSJeremy L Thompson       for (CeedInt k = 0; k < elem_size; k++) {
46*2b730f8bSJeremy L Thompson         blk_offsets[e * elem_size + k * blk_size + j] = offsets[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
47*2b730f8bSJeremy L Thompson       }
48*2b730f8bSJeremy L Thompson     }
49*2b730f8bSJeremy L Thompson   }
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 **/
72*2b730f8bSJeremy L Thompson int CeedElemRestrictionGetStrides(CeedElemRestriction rstr, CeedInt (*strides)[3]) {
73*2b730f8bSJeremy L Thompson   if (!rstr->strides) {
74a681ae63Sjeremylt     // LCOV_EXCL_START
75*2b730f8bSJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
76a681ae63Sjeremylt     // LCOV_EXCL_STOP
77*2b730f8bSJeremy L Thompson   }
78a681ae63Sjeremylt 
79*2b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*strides)[i] = rstr->strides[i];
80e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
817a982d89SJeremy L. Thompson }
827a982d89SJeremy L. Thompson 
837a982d89SJeremy L. Thompson /**
84bd33150aSjeremylt   @brief Get read-only access to a CeedElemRestriction offsets array by memtype
85bd33150aSjeremylt 
86bd33150aSjeremylt   @param rstr          CeedElemRestriction to retrieve offsets
87d1d35e2fSjeremylt   @param mem_type      Memory type on which to access the array.  If the backend
88bd33150aSjeremylt                          uses a different memory type, this will perform a copy
89bd33150aSjeremylt                          (possibly cached).
90d1d35e2fSjeremylt   @param[out] offsets  Array on memory type mem_type
91bd33150aSjeremylt 
92bd33150aSjeremylt   @return An error code: 0 - success, otherwise - failure
93bd33150aSjeremylt 
94bd33150aSjeremylt   @ref User
95bd33150aSjeremylt **/
96*2b730f8bSJeremy L Thompson int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) {
97*2b730f8bSJeremy L Thompson   if (!rstr->GetOffsets) {
98bd33150aSjeremylt     // LCOV_EXCL_START
99*2b730f8bSJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetOffsets");
100bd33150aSjeremylt     // LCOV_EXCL_STOP
101*2b730f8bSJeremy L Thompson   }
102bd33150aSjeremylt 
103*2b730f8bSJeremy L Thompson   CeedCall(rstr->GetOffsets(rstr, mem_type, offsets));
104d1d35e2fSjeremylt   rstr->num_readers++;
105e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
106430758c8SJeremy L Thompson }
107430758c8SJeremy L Thompson 
108430758c8SJeremy L Thompson /**
109430758c8SJeremy L Thompson   @brief Restore an offsets array obtained using CeedElemRestrictionGetOffsets()
110430758c8SJeremy L Thompson 
111430758c8SJeremy L Thompson   @param rstr     CeedElemRestriction to restore
112430758c8SJeremy L Thompson   @param offsets  Array of offset data
113430758c8SJeremy L Thompson 
114430758c8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
115430758c8SJeremy L Thompson 
116430758c8SJeremy L Thompson   @ref User
117430758c8SJeremy L Thompson **/
118*2b730f8bSJeremy L Thompson int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr, const CeedInt **offsets) {
119430758c8SJeremy L Thompson   *offsets = NULL;
120d1d35e2fSjeremylt   rstr->num_readers--;
121e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
122bd33150aSjeremylt }
123bd33150aSjeremylt 
124bd33150aSjeremylt /**
1253ac43b2cSJeremy L Thompson   @brief Get the strided status of a CeedElemRestriction
1263ac43b2cSJeremy L Thompson 
1273ac43b2cSJeremy L Thompson   @param rstr             CeedElemRestriction
128d1d35e2fSjeremylt   @param[out] is_strided  Variable to store strided status, 1 if strided else 0
1293ac43b2cSJeremy L Thompson 
1303ac43b2cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1313ac43b2cSJeremy L Thompson 
1323ac43b2cSJeremy L Thompson   @ref Backend
1333ac43b2cSJeremy L Thompson **/
134d1d35e2fSjeremylt int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) {
135d1d35e2fSjeremylt   *is_strided = rstr->strides ? true : false;
136e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1373ac43b2cSJeremy L Thompson }
1383ac43b2cSJeremy L Thompson 
1393ac43b2cSJeremy L Thompson /**
140b435c5a6Srezgarshakeri   @brief Get oriented status of a CeedElemRestriction
141b435c5a6Srezgarshakeri 
142b435c5a6Srezgarshakeri   @param rstr             CeedElemRestriction
143b435c5a6Srezgarshakeri   @param[out] is_oriented  Variable to store oriented status, 1 if oriented else 0
144b435c5a6Srezgarshakeri 
145b435c5a6Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
146b435c5a6Srezgarshakeri 
147b435c5a6Srezgarshakeri   @ref Backend
148b435c5a6Srezgarshakeri **/
149b435c5a6Srezgarshakeri int CeedElemRestrictionIsOriented(CeedElemRestriction rstr, bool *is_oriented) {
150b435c5a6Srezgarshakeri   *is_oriented = rstr->is_oriented;
151b435c5a6Srezgarshakeri   return CEED_ERROR_SUCCESS;
152b435c5a6Srezgarshakeri }
153b435c5a6Srezgarshakeri 
154b435c5a6Srezgarshakeri /**
155a681ae63Sjeremylt   @brief Get the backend stride status of a CeedElemRestriction
1567a982d89SJeremy L. Thompson 
1577a982d89SJeremy L. Thompson   @param rstr                      CeedElemRestriction
15896b902e2Sjeremylt   @param[out] has_backend_strides  Variable to store stride status
1597a982d89SJeremy L. Thompson 
1607a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1617a982d89SJeremy L. Thompson 
1627a982d89SJeremy L. Thompson   @ref Backend
1637a982d89SJeremy L. Thompson **/
164*2b730f8bSJeremy L Thompson int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, bool *has_backend_strides) {
165*2b730f8bSJeremy L Thompson   if (!rstr->strides) {
166a681ae63Sjeremylt     // LCOV_EXCL_START
167*2b730f8bSJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
168a681ae63Sjeremylt     // LCOV_EXCL_STOP
169*2b730f8bSJeremy L Thompson   }
1707a982d89SJeremy L. Thompson 
171*2b730f8bSJeremy L Thompson   *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
172a681ae63Sjeremylt                           (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
173e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1747a982d89SJeremy L. Thompson }
1757a982d89SJeremy L. Thompson 
1767a982d89SJeremy L. Thompson /**
17749fd234cSJeremy L Thompson 
17849fd234cSJeremy L Thompson   @brief Get the E-vector layout of a CeedElemRestriction
17949fd234cSJeremy L Thompson 
18049fd234cSJeremy L Thompson   @param rstr         CeedElemRestriction
18149fd234cSJeremy L Thompson   @param[out] layout  Variable to store layout array,
18249fd234cSJeremy L Thompson                         stored as [nodes, components, elements].
18349fd234cSJeremy L Thompson                         The data for node i, component j, element k in the
18449fd234cSJeremy L Thompson                         E-vector is given by
18595e93d34SJeremy L Thompson                         i*layout[0] + j*layout[1] + k*layout[2]
18649fd234cSJeremy L Thompson 
18749fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
18849fd234cSJeremy L Thompson 
18949fd234cSJeremy L Thompson   @ref Backend
19049fd234cSJeremy L Thompson **/
191*2b730f8bSJeremy L Thompson int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, CeedInt (*layout)[3]) {
192*2b730f8bSJeremy L Thompson   if (!rstr->layout[0]) {
19349fd234cSJeremy L Thompson     // LCOV_EXCL_START
194*2b730f8bSJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no layout data");
19549fd234cSJeremy L Thompson     // LCOV_EXCL_STOP
196*2b730f8bSJeremy L Thompson   }
19749fd234cSJeremy L Thompson 
198*2b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*layout)[i] = rstr->layout[i];
199e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
20049fd234cSJeremy L Thompson }
20149fd234cSJeremy L Thompson 
20249fd234cSJeremy L Thompson /**
20349fd234cSJeremy L Thompson 
20449fd234cSJeremy L Thompson   @brief Set the E-vector layout of a CeedElemRestriction
20549fd234cSJeremy L Thompson 
20649fd234cSJeremy L Thompson   @param rstr    CeedElemRestriction
20749fd234cSJeremy L Thompson   @param layout  Variable to containing layout array,
20849fd234cSJeremy L Thompson                    stored as [nodes, components, elements].
20949fd234cSJeremy L Thompson                    The data for node i, component j, element k in the
21049fd234cSJeremy L Thompson                    E-vector is given by
21195e93d34SJeremy L Thompson                    i*layout[0] + j*layout[1] + k*layout[2]
21249fd234cSJeremy L Thompson 
21349fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
21449fd234cSJeremy L Thompson 
21549fd234cSJeremy L Thompson   @ref Backend
21649fd234cSJeremy L Thompson **/
217*2b730f8bSJeremy L Thompson int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
218*2b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) rstr->layout[i] = layout[i];
219e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
22049fd234cSJeremy L Thompson }
22149fd234cSJeremy L Thompson 
22249fd234cSJeremy L Thompson /**
2237a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedElemRestriction
2247a982d89SJeremy L. Thompson 
2257a982d89SJeremy L. Thompson   @param rstr       CeedElemRestriction
2267a982d89SJeremy L. Thompson   @param[out] data  Variable to store data
2277a982d89SJeremy L. Thompson 
2287a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2297a982d89SJeremy L. Thompson 
2307a982d89SJeremy L. Thompson   @ref Backend
2317a982d89SJeremy L. Thompson **/
232777ff853SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) {
233777ff853SJeremy L Thompson   *(void **)data = rstr->data;
234e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2357a982d89SJeremy L. Thompson }
2367a982d89SJeremy L. Thompson 
2377a982d89SJeremy L. Thompson /**
2387a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedElemRestriction
2397a982d89SJeremy L. Thompson 
2407a982d89SJeremy L. Thompson   @param[out] rstr  CeedElemRestriction
2417a982d89SJeremy L. Thompson   @param data       Data to set
2427a982d89SJeremy L. Thompson 
2437a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2447a982d89SJeremy L. Thompson 
2457a982d89SJeremy L. Thompson   @ref Backend
2467a982d89SJeremy L. Thompson **/
247777ff853SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) {
248777ff853SJeremy L Thompson   rstr->data = data;
249e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2507a982d89SJeremy L. Thompson }
2517a982d89SJeremy L. Thompson 
25234359f16Sjeremylt /**
25334359f16Sjeremylt   @brief Increment the reference counter for a CeedElemRestriction
25434359f16Sjeremylt 
25534359f16Sjeremylt   @param rstr  ElemRestriction to increment the reference counter
25634359f16Sjeremylt 
25734359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
25834359f16Sjeremylt 
25934359f16Sjeremylt   @ref Backend
26034359f16Sjeremylt **/
2619560d06aSjeremylt int CeedElemRestrictionReference(CeedElemRestriction rstr) {
26234359f16Sjeremylt   rstr->ref_count++;
26334359f16Sjeremylt   return CEED_ERROR_SUCCESS;
26434359f16Sjeremylt }
26534359f16Sjeremylt 
2666e15d496SJeremy L Thompson /**
2676e15d496SJeremy L Thompson   @brief Estimate number of FLOPs required to apply CeedElemRestriction in t_mode
2686e15d496SJeremy L Thompson 
2696e15d496SJeremy L Thompson   @param rstr   ElemRestriction to estimate FLOPs for
2706e15d496SJeremy L Thompson   @param t_mode Apply restriction or transpose
2716e15d496SJeremy L Thompson   @param flops  Address of variable to hold FLOPs estimate
2726e15d496SJeremy L Thompson 
2736e15d496SJeremy L Thompson   @ref Backend
2746e15d496SJeremy L Thompson **/
275*2b730f8bSJeremy L Thompson int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedSize *flops) {
2766e15d496SJeremy L Thompson   bool    is_oriented;
277*2b730f8bSJeremy L Thompson   CeedInt e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp, scale = 0;
2786e15d496SJeremy L Thompson 
279*2b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionIsOriented(rstr, &is_oriented));
2806e15d496SJeremy L Thompson   switch (t_mode) {
281*2b730f8bSJeremy L Thompson     case CEED_NOTRANSPOSE:
282*2b730f8bSJeremy L Thompson       scale = is_oriented ? 1 : 0;
283*2b730f8bSJeremy L Thompson       break;
284*2b730f8bSJeremy L Thompson     case CEED_TRANSPOSE:
285*2b730f8bSJeremy L Thompson       scale = is_oriented ? 2 : 1;
286*2b730f8bSJeremy L Thompson       break;
2876e15d496SJeremy L Thompson   }
2886e15d496SJeremy L Thompson   *flops = e_size * scale;
2896e15d496SJeremy L Thompson 
2906e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2916e15d496SJeremy L Thompson }
2926e15d496SJeremy L Thompson 
2937a982d89SJeremy L. Thompson /// @}
2947a982d89SJeremy L. Thompson 
29515910d16Sjeremylt /// @cond DOXYGEN_SKIP
29615910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
29715910d16Sjeremylt /// @endcond
29815910d16Sjeremylt 
2997a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
3007a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
3017a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
3027a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
303d7b241e6Sjeremylt /// @{
304d7b241e6Sjeremylt 
3057a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
30645f1e315Sjeremylt const CeedInt CEED_STRIDES_BACKEND[3] = {0};
3077a982d89SJeremy L. Thompson 
3084cc79fe7SJed Brown /// Indicate that no CeedElemRestriction is provided by the user
309*2b730f8bSJeremy L Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = &ceed_elemrestriction_none;
3107a982d89SJeremy L. Thompson 
311d7b241e6Sjeremylt /**
312b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
313d7b241e6Sjeremylt 
314b11c1e72Sjeremylt   @param ceed         A Ceed object where the CeedElemRestriction will be created
315d1d35e2fSjeremylt   @param num_elem     Number of elements described in the @a offsets array
316d1d35e2fSjeremylt   @param elem_size    Size (number of "nodes") per element
317d1d35e2fSjeremylt   @param num_comp     Number of field components per interpolation node
31895bb1877Svaleriabarra                         (1 for scalar fields)
319d1d35e2fSjeremylt   @param comp_stride  Stride between components for the same L-vector "node".
32095e93d34SJeremy L Thompson                         Data for node i, component j, element k can be found in
32195e93d34SJeremy L Thompson                         the L-vector at index
322d1d35e2fSjeremylt                         offsets[i + k*elem_size] + j*comp_stride.
323d1d35e2fSjeremylt   @param l_size       The size of the L-vector. This vector may be larger than
324d979a051Sjeremylt                         the elements and fields given by this restriction.
325d1d35e2fSjeremylt   @param mem_type     Memory type of the @a offsets array, see CeedMemType
326d1d35e2fSjeremylt   @param copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
327d1d35e2fSjeremylt   @param offsets      Array of shape [@a num_elem, @a elem_size]. Row i holds the
328d979a051Sjeremylt                         ordered list of the offsets (into the input CeedVector)
3298795c945Sjeremylt                         for the unknowns corresponding to element i, where
330d1d35e2fSjeremylt                         0 <= i < @a num_elem. All offsets must be in the range
331d1d35e2fSjeremylt                         [0, @a l_size - 1].
3324ce2993fSjeremylt   @param[out] rstr    Address of the variable where the newly created
333b11c1e72Sjeremylt                         CeedElemRestriction will be stored
334d7b241e6Sjeremylt 
335b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
336dfdf5a53Sjeremylt 
3377a982d89SJeremy L. Thompson   @ref User
338b11c1e72Sjeremylt **/
339*2b730f8bSJeremy L Thompson int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
340*2b730f8bSJeremy L Thompson                               CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
3415fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
3425fe0d4faSjeremylt     Ceed delegate;
343*2b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
3445fe0d4faSjeremylt 
345*2b730f8bSJeremy L Thompson     if (!delegate) {
346c042f62fSJeremy L Thompson       // LCOV_EXCL_START
347*2b730f8bSJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ElemRestrictionCreate");
348c042f62fSJeremy L Thompson       // LCOV_EXCL_STOP
349*2b730f8bSJeremy L Thompson     }
3505fe0d4faSjeremylt 
351*2b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
352e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
3535fe0d4faSjeremylt   }
3545fe0d4faSjeremylt 
355*2b730f8bSJeremy L Thompson   if (elem_size < 1) {
356e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
357*2b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
358e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
359*2b730f8bSJeremy L Thompson   }
360e022e1f8SJeremy L Thompson 
361*2b730f8bSJeremy L Thompson   if (num_comp < 1) {
362e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
363*2b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
364e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
365*2b730f8bSJeremy L Thompson   }
366e022e1f8SJeremy L Thompson 
367*2b730f8bSJeremy L Thompson   if (num_comp > 1 && comp_stride < 1) {
368e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
369*2b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
370e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
371*2b730f8bSJeremy L Thompson   }
372e022e1f8SJeremy L Thompson 
373*2b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
3744ce2993fSjeremylt   (*rstr)->ceed = ceed;
375*2b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
376d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
377d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
378d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
379d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
380d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
381d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
382d1d35e2fSjeremylt   (*rstr)->num_blk     = num_elem;
383d1d35e2fSjeremylt   (*rstr)->blk_size    = 1;
384b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 0;
385*2b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, *rstr));
386e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
387d7b241e6Sjeremylt }
388d7b241e6Sjeremylt 
389d7b241e6Sjeremylt /**
390fc0567d9Srezgarshakeri   @brief Create a CeedElemRestriction with orientation sign
391fc0567d9Srezgarshakeri 
392fc0567d9Srezgarshakeri   @param ceed         A Ceed object where the CeedElemRestriction will be created
393fc0567d9Srezgarshakeri   @param num_elem     Number of elements described in the @a offsets array
394fc0567d9Srezgarshakeri   @param elem_size    Size (number of "nodes") per element
395fc0567d9Srezgarshakeri   @param num_comp     Number of field components per interpolation node
396fc0567d9Srezgarshakeri                         (1 for scalar fields)
397fc0567d9Srezgarshakeri   @param comp_stride  Stride between components for the same L-vector "node".
398fc0567d9Srezgarshakeri                         Data for node i, component j, element k can be found in
399fc0567d9Srezgarshakeri                         the L-vector at index
400fc0567d9Srezgarshakeri                         offsets[i + k*elem_size] + j*comp_stride.
401fc0567d9Srezgarshakeri   @param l_size       The size of the L-vector. This vector may be larger than
402fc0567d9Srezgarshakeri                         the elements and fields given by this restriction.
403fc0567d9Srezgarshakeri   @param mem_type     Memory type of the @a offsets array, see CeedMemType
404fc0567d9Srezgarshakeri   @param copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
405fc0567d9Srezgarshakeri   @param offsets      Array of shape [@a num_elem, @a elem_size]. Row i holds the
406fc0567d9Srezgarshakeri                         ordered list of the offsets (into the input CeedVector)
407fc0567d9Srezgarshakeri                         for the unknowns corresponding to element i, where
408fc0567d9Srezgarshakeri                         0 <= i < @a num_elem. All offsets must be in the range
409fc0567d9Srezgarshakeri                         [0, @a l_size - 1].
410fc0567d9Srezgarshakeri   @param orient       Array of shape [@a num_elem, @a elem_size] with bool false
411fc0567d9Srezgarshakeri                         for positively oriented and true to flip the orientation.
412fc0567d9Srezgarshakeri   @param[out] rstr    Address of the variable where the newly created
413fc0567d9Srezgarshakeri                         CeedElemRestriction will be stored
414fc0567d9Srezgarshakeri 
415fc0567d9Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
416fc0567d9Srezgarshakeri 
417fc0567d9Srezgarshakeri   @ref User
418fc0567d9Srezgarshakeri **/
419*2b730f8bSJeremy L Thompson int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
420*2b730f8bSJeremy L Thompson                                       CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orient,
421fc0567d9Srezgarshakeri                                       CeedElemRestriction *rstr) {
422c7745053SRezgar Shakeri   if (!ceed->ElemRestrictionCreateOriented) {
423fc0567d9Srezgarshakeri     Ceed delegate;
424*2b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
425fc0567d9Srezgarshakeri 
426*2b730f8bSJeremy L Thompson     if (!delegate) {
427fc0567d9Srezgarshakeri       // LCOV_EXCL_START
428*2b730f8bSJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateOriented");
429fc0567d9Srezgarshakeri       // LCOV_EXCL_STOP
430*2b730f8bSJeremy L Thompson     }
431fc0567d9Srezgarshakeri 
432*2b730f8bSJeremy L Thompson     CeedCall(
433*2b730f8bSJeremy L Thompson         CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, orient, rstr));
434fc0567d9Srezgarshakeri     return CEED_ERROR_SUCCESS;
435fc0567d9Srezgarshakeri   }
436fc0567d9Srezgarshakeri 
437*2b730f8bSJeremy L Thompson   if (elem_size < 1) {
438e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
439*2b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
440e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
441*2b730f8bSJeremy L Thompson   }
442e022e1f8SJeremy L Thompson 
443*2b730f8bSJeremy L Thompson   if (num_comp < 1) {
444e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
445*2b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
446e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
447*2b730f8bSJeremy L Thompson   }
448e022e1f8SJeremy L Thompson 
449*2b730f8bSJeremy L Thompson   if (num_comp > 1 && comp_stride < 1) {
450e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
451*2b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
452e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
453*2b730f8bSJeremy L Thompson   }
454e022e1f8SJeremy L Thompson 
455*2b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
456fc0567d9Srezgarshakeri   (*rstr)->ceed = ceed;
457*2b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
458fc0567d9Srezgarshakeri   (*rstr)->ref_count   = 1;
459fc0567d9Srezgarshakeri   (*rstr)->num_elem    = num_elem;
460fc0567d9Srezgarshakeri   (*rstr)->elem_size   = elem_size;
461fc0567d9Srezgarshakeri   (*rstr)->num_comp    = num_comp;
462fc0567d9Srezgarshakeri   (*rstr)->comp_stride = comp_stride;
463fc0567d9Srezgarshakeri   (*rstr)->l_size      = l_size;
464fc0567d9Srezgarshakeri   (*rstr)->num_blk     = num_elem;
465fc0567d9Srezgarshakeri   (*rstr)->blk_size    = 1;
466b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 1;
467*2b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateOriented(mem_type, copy_mode, offsets, orient, *rstr));
468fc0567d9Srezgarshakeri   return CEED_ERROR_SUCCESS;
469fc0567d9Srezgarshakeri }
470fc0567d9Srezgarshakeri 
471fc0567d9Srezgarshakeri /**
4727509a596Sjeremylt   @brief Create a strided CeedElemRestriction
473d7b241e6Sjeremylt 
474b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
475d1d35e2fSjeremylt   @param num_elem   Number of elements described by the restriction
476d1d35e2fSjeremylt   @param elem_size  Size (number of "nodes") per element
477d1d35e2fSjeremylt   @param num_comp   Number of field components per interpolation "node"
47895bb1877Svaleriabarra                       (1 for scalar fields)
479d1d35e2fSjeremylt   @param l_size     The size of the L-vector. This vector may be larger than
480d979a051Sjeremylt                       the elements and fields given by this restriction.
4817509a596Sjeremylt   @param strides    Array for strides between [nodes, components, elements].
48295e93d34SJeremy L Thompson                       Data for node i, component j, element k can be found in
48395e93d34SJeremy L Thompson                       the L-vector at index
48495e93d34SJeremy L Thompson                       i*strides[0] + j*strides[1] + k*strides[2].
48595e93d34SJeremy L Thompson                       @a CEED_STRIDES_BACKEND may be used with vectors created
48695e93d34SJeremy L Thompson                       by a Ceed backend.
4874ce2993fSjeremylt   @param rstr       Address of the variable where the newly created
488b11c1e72Sjeremylt                       CeedElemRestriction will be stored
489d7b241e6Sjeremylt 
490b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
491dfdf5a53Sjeremylt 
4927a982d89SJeremy L. Thompson   @ref User
493b11c1e72Sjeremylt **/
494*2b730f8bSJeremy L Thompson int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedSize l_size, const CeedInt strides[3],
495f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
4965fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
4975fe0d4faSjeremylt     Ceed delegate;
498*2b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
4995fe0d4faSjeremylt 
500*2b730f8bSJeremy L Thompson     if (!delegate) {
501c042f62fSJeremy L Thompson       // LCOV_EXCL_START
502*2b730f8bSJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ElemRestrictionCreate");
503c042f62fSJeremy L Thompson       // LCOV_EXCL_STOP
504*2b730f8bSJeremy L Thompson     }
5055fe0d4faSjeremylt 
506*2b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, l_size, strides, rstr));
507e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
5085fe0d4faSjeremylt   }
5095fe0d4faSjeremylt 
510*2b730f8bSJeremy L Thompson   if (elem_size < 1) {
511e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
512*2b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
513e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
514*2b730f8bSJeremy L Thompson   }
515e022e1f8SJeremy L Thompson 
516*2b730f8bSJeremy L Thompson   if (num_comp < 1) {
517e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
518*2b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
519e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
520*2b730f8bSJeremy L Thompson   }
521e022e1f8SJeremy L Thompson 
522*2b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
5234ce2993fSjeremylt   (*rstr)->ceed = ceed;
524*2b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
525d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
526d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
527d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
528d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
529d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
530d1d35e2fSjeremylt   (*rstr)->num_blk     = num_elem;
531d1d35e2fSjeremylt   (*rstr)->blk_size    = 1;
532b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 0;
533*2b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
534*2b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
535*2b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, *rstr));
536e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
537d7b241e6Sjeremylt }
538d7b241e6Sjeremylt 
539d7b241e6Sjeremylt /**
540b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
541d7b241e6Sjeremylt 
542d7b241e6Sjeremylt   @param ceed         A Ceed object where the CeedElemRestriction will be created.
543d1d35e2fSjeremylt   @param num_elem     Number of elements described in the @a offsets array.
544d1d35e2fSjeremylt   @param elem_size    Size (number of unknowns) per element
545d1d35e2fSjeremylt   @param blk_size     Number of elements in a block
546d1d35e2fSjeremylt   @param num_comp     Number of field components per interpolation node
54795bb1877Svaleriabarra                         (1 for scalar fields)
548d1d35e2fSjeremylt   @param comp_stride  Stride between components for the same L-vector "node".
54995e93d34SJeremy L Thompson                         Data for node i, component j, element k can be found in
55095e93d34SJeremy L Thompson                         the L-vector at index
551d1d35e2fSjeremylt                         offsets[i + k*elem_size] + j*comp_stride.
552d1d35e2fSjeremylt   @param l_size       The size of the L-vector. This vector may be larger than
553d979a051Sjeremylt                         the elements and fields given by this restriction.
554d1d35e2fSjeremylt   @param mem_type     Memory type of the @a offsets array, see CeedMemType
555d1d35e2fSjeremylt   @param copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
556d1d35e2fSjeremylt   @param offsets      Array of shape [@a num_elem, @a elem_size]. Row i holds the
557d979a051Sjeremylt                         ordered list of the offsets (into the input CeedVector)
5588795c945Sjeremylt                         for the unknowns corresponding to element i, where
559d1d35e2fSjeremylt                         0 <= i < @a num_elem. All offsets must be in the range
560d1d35e2fSjeremylt                         [0, @a l_size - 1]. The backend will permute and pad this
5618795c945Sjeremylt                         array to the desired ordering for the blocksize, which is
5628795c945Sjeremylt                         typically given by the backend. The default reordering is
5638795c945Sjeremylt                         to interlace elements.
5644ce2993fSjeremylt   @param rstr         Address of the variable where the newly created
565b11c1e72Sjeremylt                         CeedElemRestriction will be stored
566d7b241e6Sjeremylt 
567b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
568dfdf5a53Sjeremylt 
5697a982d89SJeremy L. Thompson   @ref Backend
570b11c1e72Sjeremylt  **/
571*2b730f8bSJeremy L Thompson int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedInt comp_stride,
572*2b730f8bSJeremy L Thompson                                      CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets,
5734ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
574d1d35e2fSjeremylt   CeedInt *blk_offsets;
575d1d35e2fSjeremylt   CeedInt  num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
576d7b241e6Sjeremylt 
5775fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
5785fe0d4faSjeremylt     Ceed delegate;
579*2b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
5805fe0d4faSjeremylt 
581*2b730f8bSJeremy L Thompson     if (!delegate) {
582c042f62fSJeremy L Thompson       // LCOV_EXCL_START
583*2b730f8bSJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ElemRestrictionCreateBlocked");
584c042f62fSJeremy L Thompson       // LCOV_EXCL_STOP
585*2b730f8bSJeremy L Thompson     }
5865fe0d4faSjeremylt 
587*2b730f8bSJeremy L Thompson     CeedCall(
588*2b730f8bSJeremy L Thompson         CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, blk_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
589e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
5905fe0d4faSjeremylt   }
591d7b241e6Sjeremylt 
592*2b730f8bSJeremy L Thompson   if (elem_size < 1) {
593e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
594*2b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
595e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
596*2b730f8bSJeremy L Thompson   }
597e022e1f8SJeremy L Thompson 
598*2b730f8bSJeremy L Thompson   if (blk_size < 1) {
599e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
600*2b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
601e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
602*2b730f8bSJeremy L Thompson   }
603e022e1f8SJeremy L Thompson 
604*2b730f8bSJeremy L Thompson   if (num_comp < 1) {
605e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
606*2b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
607e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
608*2b730f8bSJeremy L Thompson   }
609e022e1f8SJeremy L Thompson 
610*2b730f8bSJeremy L Thompson   if (num_comp > 1 && comp_stride < 1) {
611e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
612*2b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
613e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
614*2b730f8bSJeremy L Thompson   }
615e022e1f8SJeremy L Thompson 
616*2b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
617d7b241e6Sjeremylt 
618*2b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(num_blk * blk_size * elem_size, &blk_offsets));
619*2b730f8bSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size, elem_size));
620d7b241e6Sjeremylt 
6214ce2993fSjeremylt   (*rstr)->ceed = ceed;
622*2b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
623d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
624d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
625d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
626d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
627d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
628d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
629d1d35e2fSjeremylt   (*rstr)->num_blk     = num_blk;
630d1d35e2fSjeremylt   (*rstr)->blk_size    = blk_size;
631b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 0;
632*2b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)blk_offsets, *rstr));
633d1d35e2fSjeremylt   if (copy_mode == CEED_OWN_POINTER) {
634*2b730f8bSJeremy L Thompson     CeedCall(CeedFree(&offsets));
6351d102b48SJeremy L Thompson   }
636e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
637d7b241e6Sjeremylt }
638d7b241e6Sjeremylt 
639b11c1e72Sjeremylt /**
6407509a596Sjeremylt   @brief Create a blocked strided CeedElemRestriction
6417509a596Sjeremylt 
6427509a596Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
643d1d35e2fSjeremylt   @param num_elem   Number of elements described by the restriction
644d1d35e2fSjeremylt   @param elem_size  Size (number of "nodes") per element
645d1d35e2fSjeremylt   @param blk_size   Number of elements in a block
646d1d35e2fSjeremylt   @param num_comp   Number of field components per interpolation node
6477509a596Sjeremylt                       (1 for scalar fields)
648d1d35e2fSjeremylt   @param l_size     The size of the L-vector. This vector may be larger than
649d979a051Sjeremylt                       the elements and fields given by this restriction.
6507509a596Sjeremylt   @param strides    Array for strides between [nodes, components, elements].
65195e93d34SJeremy L Thompson                       Data for node i, component j, element k can be found in
65295e93d34SJeremy L Thompson                       the L-vector at index
65395e93d34SJeremy L Thompson                       i*strides[0] + j*strides[1] + k*strides[2].
65495e93d34SJeremy L Thompson                       @a CEED_STRIDES_BACKEND may be used with vectors created
65595e93d34SJeremy L Thompson                       by a Ceed backend.
6567509a596Sjeremylt   @param rstr       Address of the variable where the newly created
6577509a596Sjeremylt                       CeedElemRestriction will be stored
6587509a596Sjeremylt 
6597509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
6607509a596Sjeremylt 
6617a982d89SJeremy L. Thompson   @ref User
6627509a596Sjeremylt **/
663*2b730f8bSJeremy L Thompson int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedSize l_size,
6648621c6c6SJeremy L Thompson                                             const CeedInt strides[3], CeedElemRestriction *rstr) {
665d1d35e2fSjeremylt   CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
6667509a596Sjeremylt 
6677509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
6687509a596Sjeremylt     Ceed delegate;
669*2b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
6707509a596Sjeremylt 
671*2b730f8bSJeremy L Thompson     if (!delegate) {
6727509a596Sjeremylt       // LCOV_EXCL_START
673*2b730f8bSJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ElemRestrictionCreateBlocked");
6747509a596Sjeremylt       // LCOV_EXCL_STOP
675*2b730f8bSJeremy L Thompson     }
6767509a596Sjeremylt 
677*2b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, blk_size, num_comp, l_size, strides, rstr));
678e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6797509a596Sjeremylt   }
6807509a596Sjeremylt 
681*2b730f8bSJeremy L Thompson   if (elem_size < 1) {
682e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
683*2b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
684e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
685*2b730f8bSJeremy L Thompson   }
686e022e1f8SJeremy L Thompson 
687*2b730f8bSJeremy L Thompson   if (blk_size < 1) {
688e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
689*2b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
690e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
691*2b730f8bSJeremy L Thompson   }
692e022e1f8SJeremy L Thompson 
693*2b730f8bSJeremy L Thompson   if (num_comp < 1) {
694e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
695*2b730f8bSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
696e022e1f8SJeremy L Thompson     // LCOV_EXCL_STOP
697*2b730f8bSJeremy L Thompson   }
698e022e1f8SJeremy L Thompson 
699*2b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
7007509a596Sjeremylt 
7017509a596Sjeremylt   (*rstr)->ceed = ceed;
702*2b730f8bSJeremy L Thompson   CeedCall(CeedReference(ceed));
703d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
704d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
705d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
706d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
707d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
708d1d35e2fSjeremylt   (*rstr)->num_blk     = num_blk;
709d1d35e2fSjeremylt   (*rstr)->blk_size    = blk_size;
710b435c5a6Srezgarshakeri   (*rstr)->is_oriented = 0;
711*2b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
712*2b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
713*2b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, *rstr));
714e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
7157509a596Sjeremylt }
7167509a596Sjeremylt 
7177509a596Sjeremylt /**
7189560d06aSjeremylt   @brief Copy the pointer to a CeedElemRestriction. Both pointers should
7199560d06aSjeremylt            be destroyed with `CeedElemRestrictionDestroy()`;
7209560d06aSjeremylt            Note: If `*rstr_copy` is non-NULL, then it is assumed that
7219560d06aSjeremylt            `*rstr_copy` is a pointer to a CeedElemRestriction. This
7229560d06aSjeremylt            CeedElemRestriction will be destroyed if `*rstr_copy` is the
7239560d06aSjeremylt            only reference to this CeedElemRestriction.
7249560d06aSjeremylt 
7259560d06aSjeremylt   @param rstr            CeedElemRestriction to copy reference to
7269560d06aSjeremylt   @param[out] rstr_copy  Variable to store copied reference
7279560d06aSjeremylt 
7289560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
7299560d06aSjeremylt 
7309560d06aSjeremylt   @ref User
7319560d06aSjeremylt **/
732*2b730f8bSJeremy L Thompson int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_copy) {
733*2b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionReference(rstr));
734*2b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionDestroy(rstr_copy));
7359560d06aSjeremylt   *rstr_copy = rstr;
7369560d06aSjeremylt   return CEED_ERROR_SUCCESS;
7379560d06aSjeremylt }
7389560d06aSjeremylt 
7399560d06aSjeremylt /**
740b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
741b11c1e72Sjeremylt 
7424ce2993fSjeremylt   @param rstr   CeedElemRestriction
743d1d35e2fSjeremylt   @param l_vec  The address of the L-vector to be created, or NULL
744d1d35e2fSjeremylt   @param e_vec  The address of the E-vector to be created, or NULL
745b11c1e72Sjeremylt 
746b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
747dfdf5a53Sjeremylt 
7487a982d89SJeremy L. Thompson   @ref User
749b11c1e72Sjeremylt **/
750*2b730f8bSJeremy L Thompson int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, CeedVector *e_vec) {
751d2643443SJeremy L Thompson   CeedSize e_size, l_size;
752d1d35e2fSjeremylt   l_size = rstr->l_size;
753d1d35e2fSjeremylt   e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
754*2b730f8bSJeremy L Thompson   if (l_vec) CeedCall(CeedVectorCreate(rstr->ceed, l_size, l_vec));
755*2b730f8bSJeremy L Thompson   if (e_vec) CeedCall(CeedVectorCreate(rstr->ceed, e_size, e_vec));
756e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
757d7b241e6Sjeremylt }
758d7b241e6Sjeremylt 
759d7b241e6Sjeremylt /**
760d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
761d7b241e6Sjeremylt 
7624ce2993fSjeremylt   @param rstr    CeedElemRestriction
763d1d35e2fSjeremylt   @param t_mode  Apply restriction or transpose
764d1d35e2fSjeremylt   @param u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
765d1d35e2fSjeremylt   @param ru      Output vector (of shape [@a num_elem * @a elem_size] when
766d1d35e2fSjeremylt                    t_mode=@ref CEED_NOTRANSPOSE). Ordering of the e-vector is decided
7677aaeacdcSjeremylt                    by the backend.
7684cc79fe7SJed Brown   @param request Request or @ref CEED_REQUEST_IMMEDIATE
769b11c1e72Sjeremylt 
770b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
771dfdf5a53Sjeremylt 
7727a982d89SJeremy L. Thompson   @ref User
773b11c1e72Sjeremylt **/
774*2b730f8bSJeremy L Thompson int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
775d7b241e6Sjeremylt   CeedInt m, n;
776d7b241e6Sjeremylt 
777d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
778d1d35e2fSjeremylt     m = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
779d1d35e2fSjeremylt     n = rstr->l_size;
780d7b241e6Sjeremylt   } else {
781d1d35e2fSjeremylt     m = rstr->l_size;
782d1d35e2fSjeremylt     n = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
783d7b241e6Sjeremylt   }
784*2b730f8bSJeremy L Thompson   if (n != u->length) {
785c042f62fSJeremy L Thompson     // LCOV_EXCL_START
786e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
787*2b730f8bSJeremy L Thompson                      "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m,
788*2b730f8bSJeremy L Thompson                      n);
789c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
79052b3e6a7SJed Brown   }
791*2b730f8bSJeremy L Thompson   if (m != ru->length) {
792*2b730f8bSJeremy L Thompson     // LCOV_EXCL_START
793*2b730f8bSJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
794*2b730f8bSJeremy L Thompson                      "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length,
795*2b730f8bSJeremy L Thompson                      m, n);
796*2b730f8bSJeremy L Thompson     // LCOV_EXCL_STOP
797*2b730f8bSJeremy L Thompson   }
798*2b730f8bSJeremy L Thompson   if (rstr->num_elem > 0) CeedCall(rstr->Apply(rstr, t_mode, u, ru, request));
799e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
800d7b241e6Sjeremylt }
801d7b241e6Sjeremylt 
802d7b241e6Sjeremylt /**
803d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
804be9261b7Sjeremylt 
805be9261b7Sjeremylt   @param rstr    CeedElemRestriction
8061f37b403Sjeremylt   @param block   Block number to restrict to/from, i.e. block=0 will handle
807d1d35e2fSjeremylt                    elements [0 : blk_size] and block=3 will handle elements
808d1d35e2fSjeremylt                    [3*blk_size : 4*blk_size]
809d1d35e2fSjeremylt   @param t_mode  Apply restriction or transpose
810d1d35e2fSjeremylt   @param u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
811d1d35e2fSjeremylt   @param ru      Output vector (of shape [@a blk_size * @a elem_size] when
812d1d35e2fSjeremylt                    t_mode=@ref CEED_NOTRANSPOSE). Ordering of the e-vector is decided
8137aaeacdcSjeremylt                    by the backend.
8144cc79fe7SJed Brown   @param request Request or @ref CEED_REQUEST_IMMEDIATE
815be9261b7Sjeremylt 
816be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
817be9261b7Sjeremylt 
8187a982d89SJeremy L. Thompson   @ref Backend
819be9261b7Sjeremylt **/
820*2b730f8bSJeremy L Thompson int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
821*2b730f8bSJeremy L Thompson                                   CeedRequest *request) {
822be9261b7Sjeremylt   CeedInt m, n;
823be9261b7Sjeremylt 
824d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
825d1d35e2fSjeremylt     m = rstr->blk_size * rstr->elem_size * rstr->num_comp;
826d1d35e2fSjeremylt     n = rstr->l_size;
827be9261b7Sjeremylt   } else {
828d1d35e2fSjeremylt     m = rstr->l_size;
829d1d35e2fSjeremylt     n = rstr->blk_size * rstr->elem_size * rstr->num_comp;
830be9261b7Sjeremylt   }
831*2b730f8bSJeremy L Thompson   if (n != u->length) {
832c042f62fSJeremy L Thompson     // LCOV_EXCL_START
833e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
834*2b730f8bSJeremy L Thompson                      "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m,
835*2b730f8bSJeremy L Thompson                      n);
836c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
837*2b730f8bSJeremy L Thompson   }
838*2b730f8bSJeremy L Thompson   if (m != ru->length) {
839c042f62fSJeremy L Thompson     // LCOV_EXCL_START
840e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
841*2b730f8bSJeremy L Thompson                      "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length,
842*2b730f8bSJeremy L Thompson                      m, n);
843c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
844*2b730f8bSJeremy L Thompson   }
845*2b730f8bSJeremy L Thompson   if (rstr->blk_size * block > rstr->num_elem) {
846c042f62fSJeremy L Thompson     // LCOV_EXCL_START
847e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
848*2b730f8bSJeremy L Thompson                      "Cannot retrieve block %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", block,
849*2b730f8bSJeremy L Thompson                      rstr->blk_size * block, rstr->num_elem);
850c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
851*2b730f8bSJeremy L Thompson   }
852*2b730f8bSJeremy L Thompson   CeedCall(rstr->ApplyBlock(rstr, block, t_mode, u, ru, request));
853e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
854be9261b7Sjeremylt }
855be9261b7Sjeremylt 
856be9261b7Sjeremylt /**
857b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedElemRestriction
858b7c9bbdaSJeremy L Thompson 
859b7c9bbdaSJeremy L Thompson   @param rstr       CeedElemRestriction
860b7c9bbdaSJeremy L Thompson   @param[out] ceed  Variable to store Ceed
861b7c9bbdaSJeremy L Thompson 
862b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
863b7c9bbdaSJeremy L Thompson 
864b7c9bbdaSJeremy L Thompson   @ref Advanced
865b7c9bbdaSJeremy L Thompson **/
866b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
867b7c9bbdaSJeremy L Thompson   *ceed = rstr->ceed;
868b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
869b7c9bbdaSJeremy L Thompson }
870b7c9bbdaSJeremy L Thompson 
871b7c9bbdaSJeremy L Thompson /**
872d979a051Sjeremylt   @brief Get the L-vector component stride
873a681ae63Sjeremylt 
874a681ae63Sjeremylt   @param rstr              CeedElemRestriction
875d1d35e2fSjeremylt   @param[out] comp_stride  Variable to store component stride
876a681ae63Sjeremylt 
877a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
878a681ae63Sjeremylt 
879b7c9bbdaSJeremy L Thompson   @ref Advanced
880a681ae63Sjeremylt **/
881*2b730f8bSJeremy L Thompson int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, CeedInt *comp_stride) {
882d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
883e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
884a681ae63Sjeremylt }
885a681ae63Sjeremylt 
886a681ae63Sjeremylt /**
887a681ae63Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
888a681ae63Sjeremylt 
889a681ae63Sjeremylt   @param rstr           CeedElemRestriction
890d1d35e2fSjeremylt   @param[out] num_elem  Variable to store number of elements
891a681ae63Sjeremylt 
892a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
893a681ae63Sjeremylt 
894b7c9bbdaSJeremy L Thompson   @ref Advanced
895a681ae63Sjeremylt **/
896*2b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, CeedInt *num_elem) {
897d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
898e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
899a681ae63Sjeremylt }
900a681ae63Sjeremylt 
901a681ae63Sjeremylt /**
902a681ae63Sjeremylt   @brief Get the size of elements in the CeedElemRestriction
903a681ae63Sjeremylt 
904a681ae63Sjeremylt   @param rstr            CeedElemRestriction
905d1d35e2fSjeremylt   @param[out] elem_size  Variable to store size of elements
906a681ae63Sjeremylt 
907a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
908a681ae63Sjeremylt 
909b7c9bbdaSJeremy L Thompson   @ref Advanced
910a681ae63Sjeremylt **/
911*2b730f8bSJeremy L Thompson int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, CeedInt *elem_size) {
912d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
913e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
914a681ae63Sjeremylt }
915a681ae63Sjeremylt 
916a681ae63Sjeremylt /**
917d979a051Sjeremylt   @brief Get the size of the l-vector for a CeedElemRestriction
918a681ae63Sjeremylt 
919a681ae63Sjeremylt   @param rstr         CeedElemRestriction
920d1d35e2fSjeremylt   @param[out] l_size  Variable to store number of nodes
921a681ae63Sjeremylt 
922a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
923a681ae63Sjeremylt 
924b7c9bbdaSJeremy L Thompson   @ref Advanced
925a681ae63Sjeremylt **/
926*2b730f8bSJeremy L Thompson int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, CeedSize *l_size) {
927d1d35e2fSjeremylt   *l_size = rstr->l_size;
928e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
929a681ae63Sjeremylt }
930a681ae63Sjeremylt 
931a681ae63Sjeremylt /**
932a681ae63Sjeremylt   @brief Get the number of components in the elements of a
933a681ae63Sjeremylt          CeedElemRestriction
934a681ae63Sjeremylt 
935a681ae63Sjeremylt   @param rstr           CeedElemRestriction
936d1d35e2fSjeremylt   @param[out] num_comp  Variable to store number of components
937a681ae63Sjeremylt 
938a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
939a681ae63Sjeremylt 
940b7c9bbdaSJeremy L Thompson   @ref Advanced
941a681ae63Sjeremylt **/
942*2b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, CeedInt *num_comp) {
943d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
944e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
945a681ae63Sjeremylt }
946a681ae63Sjeremylt 
947a681ae63Sjeremylt /**
948a681ae63Sjeremylt   @brief Get the number of blocks in a CeedElemRestriction
949a681ae63Sjeremylt 
950a681ae63Sjeremylt   @param rstr            CeedElemRestriction
951d1d35e2fSjeremylt   @param[out] num_block  Variable to store number of blocks
952a681ae63Sjeremylt 
953a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
954a681ae63Sjeremylt 
955b7c9bbdaSJeremy L Thompson   @ref Advanced
956a681ae63Sjeremylt **/
957*2b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, CeedInt *num_block) {
958d1d35e2fSjeremylt   *num_block = rstr->num_blk;
959e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
960a681ae63Sjeremylt }
961a681ae63Sjeremylt 
962a681ae63Sjeremylt /**
963a681ae63Sjeremylt   @brief Get the size of blocks in the CeedElemRestriction
964a681ae63Sjeremylt 
965a681ae63Sjeremylt   @param rstr           CeedElemRestriction
966d1d35e2fSjeremylt   @param[out] blk_size  Variable to store size of blocks
967a681ae63Sjeremylt 
968a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
969a681ae63Sjeremylt 
970b7c9bbdaSJeremy L Thompson   @ref Advanced
971a681ae63Sjeremylt **/
972*2b730f8bSJeremy L Thompson int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, CeedInt *blk_size) {
973d1d35e2fSjeremylt   *blk_size = rstr->blk_size;
974e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
975a681ae63Sjeremylt }
976a681ae63Sjeremylt 
977a681ae63Sjeremylt /**
978d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
9791469ee4dSjeremylt 
9801469ee4dSjeremylt   @param rstr       CeedElemRestriction
981d1d35e2fSjeremylt   @param[out] mult  Vector to store multiplicity (of size l_size)
9821469ee4dSjeremylt 
9831469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
9841469ee4dSjeremylt 
9857a982d89SJeremy L. Thompson   @ref User
9861469ee4dSjeremylt **/
987*2b730f8bSJeremy L Thompson int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, CeedVector mult) {
988d1d35e2fSjeremylt   CeedVector e_vec;
9891469ee4dSjeremylt 
99025509ebbSRezgar Shakeri   // Create e_vec to hold intermediate computation in E^T (E 1)
991*2b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionCreateVector(rstr, NULL, &e_vec));
9921469ee4dSjeremylt 
99325509ebbSRezgar Shakeri   // Compute e_vec = E * 1
994*2b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 1.0));
995*2b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, CEED_REQUEST_IMMEDIATE));
99625509ebbSRezgar Shakeri   // Compute multiplicity, mult = E^T * e_vec = E^T (E 1)
997*2b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 0.0));
998*2b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, CEED_REQUEST_IMMEDIATE));
9991469ee4dSjeremylt   // Cleanup
1000*2b730f8bSJeremy L Thompson   CeedCall(CeedVectorDestroy(&e_vec));
1001e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
10021469ee4dSjeremylt }
10031469ee4dSjeremylt 
10041469ee4dSjeremylt /**
1005f02ca4a2SJed Brown   @brief View a CeedElemRestriction
1006f02ca4a2SJed Brown 
1007f02ca4a2SJed Brown   @param[in] rstr    CeedElemRestriction to view
1008f02ca4a2SJed Brown   @param[in] stream  Stream to write; typically stdout/stderr or a file
1009f02ca4a2SJed Brown 
1010f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
1011f02ca4a2SJed Brown 
10127a982d89SJeremy L. Thompson   @ref User
1013f02ca4a2SJed Brown **/
1014f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
10157509a596Sjeremylt   char stridesstr[500];
1016*2b730f8bSJeremy L Thompson   if (rstr->strides) {
1017*2b730f8bSJeremy L Thompson     sprintf(stridesstr, "[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "]", rstr->strides[0], rstr->strides[1], rstr->strides[2]);
1018*2b730f8bSJeremy L Thompson   } else {
1019990fdeb6SJeremy L Thompson     sprintf(stridesstr, "%" CeedInt_FMT, rstr->comp_stride);
1020*2b730f8bSJeremy L Thompson   }
10217509a596Sjeremylt 
1022*2b730f8bSJeremy L Thompson   fprintf(stream, "%sCeedElemRestriction from (%td, %" CeedInt_FMT ") to %" CeedInt_FMT " elements with %" CeedInt_FMT " nodes each and %s %s\n",
1023*2b730f8bSJeremy L Thompson           rstr->blk_size > 1 ? "Blocked " : "", rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
1024d979a051Sjeremylt           rstr->strides ? "strides" : "component stride", stridesstr);
1025e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1026f02ca4a2SJed Brown }
1027f02ca4a2SJed Brown 
1028f02ca4a2SJed Brown /**
1029b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
1030b11c1e72Sjeremylt 
10314ce2993fSjeremylt   @param rstr  CeedElemRestriction to destroy
1032b11c1e72Sjeremylt 
1033b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1034dfdf5a53Sjeremylt 
10357a982d89SJeremy L. Thompson   @ref User
1036b11c1e72Sjeremylt **/
10374ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
1038d1d35e2fSjeremylt   if (!*rstr || --(*rstr)->ref_count > 0) return CEED_ERROR_SUCCESS;
1039*2b730f8bSJeremy L Thompson   if ((*rstr)->num_readers) {
10408229195eSjeremylt     // LCOV_EXCL_START
1041*2b730f8bSJeremy L Thompson     return CeedError((*rstr)->ceed, CEED_ERROR_ACCESS, "Cannot destroy CeedElemRestriction, a process has read access to the offset data");
10428229195eSjeremylt     // LCOV_EXCL_STOP
1043d7b241e6Sjeremylt   }
1044*2b730f8bSJeremy L Thompson   if ((*rstr)->Destroy) CeedCall((*rstr)->Destroy(*rstr));
1045*2b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*rstr)->strides));
1046*2b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*rstr)->ceed));
1047*2b730f8bSJeremy L Thompson   CeedCall(CeedFree(rstr));
1048e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1049d7b241e6Sjeremylt }
1050d7b241e6Sjeremylt 
1051d7b241e6Sjeremylt /// @}
1052