xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-elemrestriction.c (revision e022e1f89e85f2e46b1310d6193ff8d6a4674140)
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)
46d1d35e2fSjeremylt     for (int j=0; j<blk_size; j++)
47d1d35e2fSjeremylt       for (int 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 
80a681ae63Sjeremylt   for (int 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 
20849fd234cSJeremy L Thompson   for (int 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]) {
23049fd234cSJeremy L Thompson   for (int 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 
377*e022e1f8SJeremy L Thompson   if (elem_size < 1)
378*e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
379*e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
380*e022e1f8SJeremy L Thompson                      "Element size must be at least 1");
381*e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
382*e022e1f8SJeremy L Thompson 
383*e022e1f8SJeremy L Thompson   if (num_comp < 1)
384*e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
385*e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
386*e022e1f8SJeremy L Thompson                      "ElemRestriction must have at least 1 component");
387*e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
388*e022e1f8SJeremy L Thompson 
389*e022e1f8SJeremy L Thompson   if (comp_stride < 1)
390*e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
391*e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
392*e022e1f8SJeremy L Thompson                      "ElemRestriction component stride must be at least 1");
393*e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
394*e022e1f8SJeremy 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 
467*e022e1f8SJeremy L Thompson   if (elem_size < 1)
468*e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
469*e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
470*e022e1f8SJeremy L Thompson                      "Element size must be at least 1");
471*e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
472*e022e1f8SJeremy L Thompson 
473*e022e1f8SJeremy L Thompson   if (num_comp < 1)
474*e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
475*e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
476*e022e1f8SJeremy L Thompson                      "ElemRestriction must have at least 1 component");
477*e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
478*e022e1f8SJeremy L Thompson 
479*e022e1f8SJeremy L Thompson   if (comp_stride < 1)
480*e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
481*e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
482*e022e1f8SJeremy L Thompson                      "ElemRestriction component stride must be at least 1");
483*e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
484*e022e1f8SJeremy 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 
549*e022e1f8SJeremy L Thompson   if (elem_size < 1)
550*e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
551*e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
552*e022e1f8SJeremy L Thompson                      "Element size must be at least 1");
553*e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
554*e022e1f8SJeremy L Thompson 
555*e022e1f8SJeremy L Thompson   if (num_comp < 1)
556*e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
557*e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
558*e022e1f8SJeremy L Thompson                      "ElemRestriction must have at least 1 component");
559*e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
560*e022e1f8SJeremy 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);
5737509a596Sjeremylt   for (int 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 
642*e022e1f8SJeremy L Thompson   if (elem_size < 1)
643*e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
644*e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
645*e022e1f8SJeremy L Thompson                      "Element size must be at least 1");
646*e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
647*e022e1f8SJeremy L Thompson 
648*e022e1f8SJeremy L Thompson   if (blk_size < 1)
649*e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
650*e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
651*e022e1f8SJeremy L Thompson                      "Block size must be at least 1");
652*e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
653*e022e1f8SJeremy L Thompson 
654*e022e1f8SJeremy L Thompson   if (num_comp < 1)
655*e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
656*e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
657*e022e1f8SJeremy L Thompson                      "ElemRestriction must have at least 1 component");
658*e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
659*e022e1f8SJeremy L Thompson 
660*e022e1f8SJeremy L Thompson   if (comp_stride < 1)
661*e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
662*e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
663*e022e1f8SJeremy L Thompson                      "ElemRestriction component stride must be at least 1");
664*e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
665*e022e1f8SJeremy 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 
737*e022e1f8SJeremy L Thompson   if (elem_size < 1)
738*e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
739*e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
740*e022e1f8SJeremy L Thompson                      "Element size must be at least 1");
741*e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
742*e022e1f8SJeremy L Thompson 
743*e022e1f8SJeremy L Thompson   if (blk_size < 1)
744*e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
745*e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
746*e022e1f8SJeremy L Thompson                      "Block size must be at least 1");
747*e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
748*e022e1f8SJeremy L Thompson 
749*e022e1f8SJeremy L Thompson   if (num_comp < 1)
750*e022e1f8SJeremy L Thompson     // LCOV_EXCL_START
751*e022e1f8SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_DIMENSION,
752*e022e1f8SJeremy L Thompson                      "ElemRestriction must have at least 1 component");
753*e022e1f8SJeremy L Thompson   // LCOV_EXCL_STOP
754*e022e1f8SJeremy 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);
7687509a596Sjeremylt   for (int 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
866d1d35e2fSjeremylt   ierr = rstr->Apply(rstr, t_mode, u, ru, request); CeedChk(ierr);
867e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
868d7b241e6Sjeremylt }
869d7b241e6Sjeremylt 
870d7b241e6Sjeremylt /**
871d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
872be9261b7Sjeremylt 
873be9261b7Sjeremylt   @param rstr    CeedElemRestriction
8741f37b403Sjeremylt   @param block   Block number to restrict to/from, i.e. block=0 will handle
875d1d35e2fSjeremylt                    elements [0 : blk_size] and block=3 will handle elements
876d1d35e2fSjeremylt                    [3*blk_size : 4*blk_size]
877d1d35e2fSjeremylt   @param t_mode  Apply restriction or transpose
878d1d35e2fSjeremylt   @param u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
879d1d35e2fSjeremylt   @param ru      Output vector (of shape [@a blk_size * @a elem_size] when
880d1d35e2fSjeremylt                    t_mode=@ref CEED_NOTRANSPOSE). Ordering of the e-vector is decided
8817aaeacdcSjeremylt                    by the backend.
8824cc79fe7SJed Brown   @param request Request or @ref CEED_REQUEST_IMMEDIATE
883be9261b7Sjeremylt 
884be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
885be9261b7Sjeremylt 
8867a982d89SJeremy L. Thompson   @ref Backend
887be9261b7Sjeremylt **/
888be9261b7Sjeremylt int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block,
889d1d35e2fSjeremylt                                   CeedTransposeMode t_mode, CeedVector u,
890a8d32208Sjeremylt                                   CeedVector ru, CeedRequest *request) {
891be9261b7Sjeremylt   CeedInt m, n;
892be9261b7Sjeremylt   int ierr;
893be9261b7Sjeremylt 
894d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
895d1d35e2fSjeremylt     m = rstr->blk_size * rstr->elem_size * rstr->num_comp;
896d1d35e2fSjeremylt     n = rstr->l_size;
897be9261b7Sjeremylt   } else {
898d1d35e2fSjeremylt     m = rstr->l_size;
899d1d35e2fSjeremylt     n = rstr->blk_size * rstr->elem_size * rstr->num_comp;
900be9261b7Sjeremylt   }
901be9261b7Sjeremylt   if (n != u->length)
902c042f62fSJeremy L Thompson     // LCOV_EXCL_START
903e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
904e15f9bd0SJeremy L Thompson                      "Input vector size %d not compatible with "
9051d102b48SJeremy L Thompson                      "element restriction (%d, %d)", u->length, m, n);
906c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
907a8d32208Sjeremylt   if (m != ru->length)
908c042f62fSJeremy L Thompson     // LCOV_EXCL_START
909e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
910e15f9bd0SJeremy L Thompson                      "Output vector size %d not compatible with "
911a8d32208Sjeremylt                      "element restriction (%d, %d)", ru->length, m, n);
912c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
913d1d35e2fSjeremylt   if (rstr->blk_size*block > rstr->num_elem)
914c042f62fSJeremy L Thompson     // LCOV_EXCL_START
915e15f9bd0SJeremy L Thompson     return CeedError(rstr->ceed, CEED_ERROR_DIMENSION,
916e15f9bd0SJeremy L Thompson                      "Cannot retrieve block %d, element %d > "
917d1d35e2fSjeremylt                      "total elements %d", block, rstr->blk_size*block,
918d1d35e2fSjeremylt                      rstr->num_elem);
919c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
920d1d35e2fSjeremylt   ierr = rstr->ApplyBlock(rstr, block, t_mode, u, ru, request);
921be9261b7Sjeremylt   CeedChk(ierr);
922e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
923be9261b7Sjeremylt }
924be9261b7Sjeremylt 
925be9261b7Sjeremylt /**
926b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedElemRestriction
927b7c9bbdaSJeremy L Thompson 
928b7c9bbdaSJeremy L Thompson   @param rstr       CeedElemRestriction
929b7c9bbdaSJeremy L Thompson   @param[out] ceed  Variable to store Ceed
930b7c9bbdaSJeremy L Thompson 
931b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
932b7c9bbdaSJeremy L Thompson 
933b7c9bbdaSJeremy L Thompson   @ref Advanced
934b7c9bbdaSJeremy L Thompson **/
935b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
936b7c9bbdaSJeremy L Thompson   *ceed = rstr->ceed;
937b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
938b7c9bbdaSJeremy L Thompson }
939b7c9bbdaSJeremy L Thompson 
940b7c9bbdaSJeremy L Thompson /**
941d979a051Sjeremylt   @brief Get the L-vector component stride
942a681ae63Sjeremylt 
943a681ae63Sjeremylt   @param rstr              CeedElemRestriction
944d1d35e2fSjeremylt   @param[out] comp_stride  Variable to store component stride
945a681ae63Sjeremylt 
946a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
947a681ae63Sjeremylt 
948b7c9bbdaSJeremy L Thompson   @ref Advanced
949a681ae63Sjeremylt **/
950d979a051Sjeremylt int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr,
951d1d35e2fSjeremylt                                      CeedInt *comp_stride) {
952d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
953e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
954a681ae63Sjeremylt }
955a681ae63Sjeremylt 
956a681ae63Sjeremylt /**
957a681ae63Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
958a681ae63Sjeremylt 
959a681ae63Sjeremylt   @param rstr           CeedElemRestriction
960d1d35e2fSjeremylt   @param[out] num_elem  Variable to store number of elements
961a681ae63Sjeremylt 
962a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
963a681ae63Sjeremylt 
964b7c9bbdaSJeremy L Thompson   @ref Advanced
965a681ae63Sjeremylt **/
966a681ae63Sjeremylt int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
967d1d35e2fSjeremylt                                       CeedInt *num_elem) {
968d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
969e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
970a681ae63Sjeremylt }
971a681ae63Sjeremylt 
972a681ae63Sjeremylt /**
973a681ae63Sjeremylt   @brief Get the size of elements in the CeedElemRestriction
974a681ae63Sjeremylt 
975a681ae63Sjeremylt   @param rstr            CeedElemRestriction
976d1d35e2fSjeremylt   @param[out] elem_size  Variable to store size of elements
977a681ae63Sjeremylt 
978a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
979a681ae63Sjeremylt 
980b7c9bbdaSJeremy L Thompson   @ref Advanced
981a681ae63Sjeremylt **/
982a681ae63Sjeremylt int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
983d1d35e2fSjeremylt                                       CeedInt *elem_size) {
984d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
985e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
986a681ae63Sjeremylt }
987a681ae63Sjeremylt 
988a681ae63Sjeremylt /**
989d979a051Sjeremylt   @brief Get the size of the l-vector for a CeedElemRestriction
990a681ae63Sjeremylt 
991a681ae63Sjeremylt   @param rstr         CeedElemRestriction
992d1d35e2fSjeremylt   @param[out] l_size  Variable to store number of nodes
993a681ae63Sjeremylt 
994a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
995a681ae63Sjeremylt 
996b7c9bbdaSJeremy L Thompson   @ref Advanced
997a681ae63Sjeremylt **/
998d979a051Sjeremylt int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr,
999e79b91d9SJeremy L Thompson                                       CeedSize *l_size) {
1000d1d35e2fSjeremylt   *l_size = rstr->l_size;
1001e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1002a681ae63Sjeremylt }
1003a681ae63Sjeremylt 
1004a681ae63Sjeremylt /**
1005a681ae63Sjeremylt   @brief Get the number of components in the elements of a
1006a681ae63Sjeremylt          CeedElemRestriction
1007a681ae63Sjeremylt 
1008a681ae63Sjeremylt   @param rstr           CeedElemRestriction
1009d1d35e2fSjeremylt   @param[out] num_comp  Variable to store number of components
1010a681ae63Sjeremylt 
1011a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1012a681ae63Sjeremylt 
1013b7c9bbdaSJeremy L Thompson   @ref Advanced
1014a681ae63Sjeremylt **/
1015a681ae63Sjeremylt int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
1016d1d35e2fSjeremylt                                         CeedInt *num_comp) {
1017d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
1018e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1019a681ae63Sjeremylt }
1020a681ae63Sjeremylt 
1021a681ae63Sjeremylt /**
1022a681ae63Sjeremylt   @brief Get the number of blocks in a CeedElemRestriction
1023a681ae63Sjeremylt 
1024a681ae63Sjeremylt   @param rstr            CeedElemRestriction
1025d1d35e2fSjeremylt   @param[out] num_block  Variable to store number of blocks
1026a681ae63Sjeremylt 
1027a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1028a681ae63Sjeremylt 
1029b7c9bbdaSJeremy L Thompson   @ref Advanced
1030a681ae63Sjeremylt **/
1031a681ae63Sjeremylt int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
1032d1d35e2fSjeremylt                                     CeedInt *num_block) {
1033d1d35e2fSjeremylt   *num_block = rstr->num_blk;
1034e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1035a681ae63Sjeremylt }
1036a681ae63Sjeremylt 
1037a681ae63Sjeremylt /**
1038a681ae63Sjeremylt   @brief Get the size of blocks in the CeedElemRestriction
1039a681ae63Sjeremylt 
1040a681ae63Sjeremylt   @param rstr           CeedElemRestriction
1041d1d35e2fSjeremylt   @param[out] blk_size  Variable to store size of blocks
1042a681ae63Sjeremylt 
1043a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1044a681ae63Sjeremylt 
1045b7c9bbdaSJeremy L Thompson   @ref Advanced
1046a681ae63Sjeremylt **/
1047a681ae63Sjeremylt int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
1048d1d35e2fSjeremylt                                     CeedInt *blk_size) {
1049d1d35e2fSjeremylt   *blk_size = rstr->blk_size;
1050e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1051a681ae63Sjeremylt }
1052a681ae63Sjeremylt 
1053a681ae63Sjeremylt /**
1054d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
10551469ee4dSjeremylt 
10561469ee4dSjeremylt   @param rstr       CeedElemRestriction
1057d1d35e2fSjeremylt   @param[out] mult  Vector to store multiplicity (of size l_size)
10581469ee4dSjeremylt 
10591469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
10601469ee4dSjeremylt 
10617a982d89SJeremy L. Thompson   @ref User
10621469ee4dSjeremylt **/
10631469ee4dSjeremylt int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr,
10641469ee4dSjeremylt                                        CeedVector mult) {
10651469ee4dSjeremylt   int ierr;
1066d1d35e2fSjeremylt   CeedVector e_vec;
10671469ee4dSjeremylt 
106825509ebbSRezgar Shakeri   // Create e_vec to hold intermediate computation in E^T (E 1)
1069d1d35e2fSjeremylt   ierr = CeedElemRestrictionCreateVector(rstr, NULL, &e_vec); CeedChk(ierr);
10701469ee4dSjeremylt 
107125509ebbSRezgar Shakeri   // Compute e_vec = E * 1
107225509ebbSRezgar Shakeri   ierr = CeedVectorSetValue(mult, 1.0); CeedChk(ierr);
107325509ebbSRezgar Shakeri   ierr = CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec,
107425509ebbSRezgar Shakeri                                   CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
107525509ebbSRezgar Shakeri   // Compute multiplicity, mult = E^T * e_vec = E^T (E 1)
107625509ebbSRezgar Shakeri   ierr = CeedVectorSetValue(mult, 0.0); CeedChk(ierr);
1077d1d35e2fSjeremylt   ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult,
1078efc78312Sjeremylt                                   CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
10791469ee4dSjeremylt   // Cleanup
1080d1d35e2fSjeremylt   ierr = CeedVectorDestroy(&e_vec); CeedChk(ierr);
1081e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
10821469ee4dSjeremylt }
10831469ee4dSjeremylt 
10841469ee4dSjeremylt /**
1085f02ca4a2SJed Brown   @brief View a CeedElemRestriction
1086f02ca4a2SJed Brown 
1087f02ca4a2SJed Brown   @param[in] rstr    CeedElemRestriction to view
1088f02ca4a2SJed Brown   @param[in] stream  Stream to write; typically stdout/stderr or a file
1089f02ca4a2SJed Brown 
1090f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
1091f02ca4a2SJed Brown 
10927a982d89SJeremy L. Thompson   @ref User
1093f02ca4a2SJed Brown **/
1094f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
10957509a596Sjeremylt   char stridesstr[500];
10967509a596Sjeremylt   if (rstr->strides)
10977509a596Sjeremylt     sprintf(stridesstr, "[%d, %d, %d]", rstr->strides[0], rstr->strides[1],
10987509a596Sjeremylt             rstr->strides[2]);
1099d979a051Sjeremylt   else
1100d1d35e2fSjeremylt     sprintf(stridesstr, "%d", rstr->comp_stride);
11017509a596Sjeremylt 
11025b76854bSJeremy L Thompson   fprintf(stream, "%sCeedElemRestriction from (%td, %d) to %d elements with %d "
1103d1d35e2fSjeremylt           "nodes each and %s %s\n", rstr->blk_size > 1 ? "Blocked " : "",
1104d1d35e2fSjeremylt           rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
1105d979a051Sjeremylt           rstr->strides ? "strides" : "component stride", stridesstr);
1106e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1107f02ca4a2SJed Brown }
1108f02ca4a2SJed Brown 
1109f02ca4a2SJed Brown /**
1110b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
1111b11c1e72Sjeremylt 
11124ce2993fSjeremylt   @param rstr  CeedElemRestriction to destroy
1113b11c1e72Sjeremylt 
1114b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1115dfdf5a53Sjeremylt 
11167a982d89SJeremy L. Thompson   @ref User
1117b11c1e72Sjeremylt **/
11184ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
1119d7b241e6Sjeremylt   int ierr;
1120d7b241e6Sjeremylt 
1121d1d35e2fSjeremylt   if (!*rstr || --(*rstr)->ref_count > 0) return CEED_ERROR_SUCCESS;
1122d1d35e2fSjeremylt   if ((*rstr)->num_readers)
11238229195eSjeremylt     // LCOV_EXCL_START
1124e15f9bd0SJeremy L Thompson     return CeedError((*rstr)->ceed, CEED_ERROR_ACCESS,
1125e15f9bd0SJeremy L Thompson                      "Cannot destroy CeedElemRestriction, "
1126430758c8SJeremy L Thompson                      "a process has read access to the offset data");
11278229195eSjeremylt   // LCOV_EXCL_STOP
11284ce2993fSjeremylt   if ((*rstr)->Destroy) {
11294ce2993fSjeremylt     ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr);
1130d7b241e6Sjeremylt   }
11317509a596Sjeremylt   ierr = CeedFree(&(*rstr)->strides); CeedChk(ierr);
11324ce2993fSjeremylt   ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr);
11334ce2993fSjeremylt   ierr = CeedFree(rstr); CeedChk(ierr);
1134e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1135d7b241e6Sjeremylt }
1136d7b241e6Sjeremylt 
1137d7b241e6Sjeremylt /// @}
1138