xref: /libCEED/interface/ceed-elemrestriction.c (revision db002c03923317a1c3814dcd861330002c00a8ea) !
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>
949aac155SJeremy L Thompson #include <ceed.h>
102b730f8bSJeremy L Thompson #include <ceed/backend.h>
113d576824SJeremy L Thompson #include <stdbool.h>
123d576824SJeremy L Thompson #include <stdio.h>
13c17ec2beSJeremy L Thompson #include <string.h>
14d7b241e6Sjeremylt 
157a982d89SJeremy L. Thompson /// @file
167a982d89SJeremy L. Thompson /// Implementation of CeedElemRestriction interfaces
177a982d89SJeremy L. Thompson 
187a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
197a982d89SJeremy L. Thompson /// CeedElemRestriction Library Internal Functions
207a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
217a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionDeveloper
227a982d89SJeremy L. Thompson /// @{
237a982d89SJeremy L. Thompson 
247a982d89SJeremy L. Thompson /**
25d979a051Sjeremylt   @brief Permute and pad offsets for a blocked restriction
267a982d89SJeremy L. Thompson 
27ea61e9acSJeremy L Thompson   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
28ea61e9acSJeremy L Thompson                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
29ea61e9acSJeremy L Thompson 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
30ea61e9acSJeremy L Thompson   @param[out] blk_offsets Array of permuted and padded offsets of shape [@a num_blk, @a elem_size, @a blk_size].
31ea61e9acSJeremy L Thompson   @param[in]  num_blk     Number of blocks
32ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements
33ea61e9acSJeremy L Thompson   @param[in]  blk_size    Number of elements in a block
34ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size of each element
357a982d89SJeremy L. Thompson 
367a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
377a982d89SJeremy L. Thompson 
387a982d89SJeremy L. Thompson   @ref Utility
397a982d89SJeremy L. Thompson **/
402b730f8bSJeremy L Thompson int CeedPermutePadOffsets(const CeedInt *offsets, CeedInt *blk_offsets, CeedInt num_blk, CeedInt num_elem, CeedInt blk_size, CeedInt elem_size) {
412b730f8bSJeremy L Thompson   for (CeedInt e = 0; e < num_blk * blk_size; e += blk_size) {
422b730f8bSJeremy L Thompson     for (CeedInt j = 0; j < blk_size; j++) {
432b730f8bSJeremy L Thompson       for (CeedInt k = 0; k < elem_size; k++) {
442b730f8bSJeremy L Thompson         blk_offsets[e * elem_size + k * blk_size + j] = offsets[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
452b730f8bSJeremy L Thompson       }
462b730f8bSJeremy L Thompson     }
472b730f8bSJeremy L Thompson   }
48e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
497a982d89SJeremy L. Thompson }
507a982d89SJeremy L. Thompson 
517a982d89SJeremy L. Thompson /// @}
527a982d89SJeremy L. Thompson 
537a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
547a982d89SJeremy L. Thompson /// CeedElemRestriction Backend API
557a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
567a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionBackend
577a982d89SJeremy L. Thompson /// @{
587a982d89SJeremy L. Thompson 
597a982d89SJeremy L. Thompson /**
6078b2e752SJeremy L Thompson   @brief Restrict an L-vector to an E-vector or apply its transpose ignoring any
6178b2e752SJeremy L Thompson          provided orientations
6278b2e752SJeremy L Thompson 
6378b2e752SJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
6478b2e752SJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
6578b2e752SJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
6678b2e752SJeremy L Thompson   @param[out] ru      Output vector (of shape [@a num_elem * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
6778b2e752SJeremy L Thompson                         Ordering of the e-vector is decided by the backend.
6878b2e752SJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
6978b2e752SJeremy L Thompson 
7078b2e752SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
7178b2e752SJeremy L Thompson 
7278b2e752SJeremy L Thompson   @ref User
7378b2e752SJeremy L Thompson **/
7478b2e752SJeremy L Thompson int CeedElemRestrictionApplyUnsigned(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
7578b2e752SJeremy L Thompson   CeedInt m, n;
7678b2e752SJeremy L Thompson 
7778b2e752SJeremy L Thompson   CeedCheck(rstr->ApplyUnsigned, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ElemRestrictionApplyUnsigned");
7878b2e752SJeremy L Thompson 
7978b2e752SJeremy L Thompson   if (t_mode == CEED_NOTRANSPOSE) {
8078b2e752SJeremy L Thompson     m = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
8178b2e752SJeremy L Thompson     n = rstr->l_size;
8278b2e752SJeremy L Thompson   } else {
8378b2e752SJeremy L Thompson     m = rstr->l_size;
8478b2e752SJeremy L Thompson     n = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
8578b2e752SJeremy L Thompson   }
8678b2e752SJeremy L Thompson   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
8778b2e752SJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
8878b2e752SJeremy L Thompson   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
8978b2e752SJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
9078b2e752SJeremy L Thompson   if (rstr->num_elem > 0) CeedCall(rstr->ApplyUnsigned(rstr, t_mode, u, ru, request));
9178b2e752SJeremy L Thompson   return CEED_ERROR_SUCCESS;
9278b2e752SJeremy L Thompson }
9378b2e752SJeremy L Thompson 
9478b2e752SJeremy L Thompson /**
95a681ae63Sjeremylt 
96a681ae63Sjeremylt   @brief Get the strides of a strided CeedElemRestriction
977a982d89SJeremy L. Thompson 
98ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
99a681ae63Sjeremylt   @param[out] strides Variable to store strides array
1007a982d89SJeremy L. Thompson 
1017a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1027a982d89SJeremy L. Thompson 
1037a982d89SJeremy L. Thompson   @ref Backend
1047a982d89SJeremy L. Thompson **/
1052b730f8bSJeremy L Thompson int CeedElemRestrictionGetStrides(CeedElemRestriction rstr, CeedInt (*strides)[3]) {
1066574a04fSJeremy L Thompson   CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
1072b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*strides)[i] = rstr->strides[i];
108e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1097a982d89SJeremy L. Thompson }
1107a982d89SJeremy L. Thompson 
1117a982d89SJeremy L. Thompson /**
112bd33150aSjeremylt   @brief Get read-only access to a CeedElemRestriction offsets array by memtype
113bd33150aSjeremylt 
114ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction to retrieve offsets
115ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the array.
116ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy (possibly cached).
117d1d35e2fSjeremylt   @param[out] offsets Array on memory type mem_type
118bd33150aSjeremylt 
119bd33150aSjeremylt   @return An error code: 0 - success, otherwise - failure
120bd33150aSjeremylt 
121bd33150aSjeremylt   @ref User
122bd33150aSjeremylt **/
1232b730f8bSJeremy L Thompson int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) {
124c17ec2beSJeremy L Thompson   if (rstr->rstr_signed) {
125c17ec2beSJeremy L Thompson     CeedCall(CeedElemRestrictionGetOffsets(rstr->rstr_signed, mem_type, offsets));
126c17ec2beSJeremy L Thompson   } else {
1276574a04fSJeremy L Thompson     CeedCheck(rstr->GetOffsets, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetOffsets");
1282b730f8bSJeremy L Thompson     CeedCall(rstr->GetOffsets(rstr, mem_type, offsets));
129d1d35e2fSjeremylt     rstr->num_readers++;
130c17ec2beSJeremy L Thompson   }
131e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
132430758c8SJeremy L Thompson }
133430758c8SJeremy L Thompson 
134430758c8SJeremy L Thompson /**
135430758c8SJeremy L Thompson   @brief Restore an offsets array obtained using CeedElemRestrictionGetOffsets()
136430758c8SJeremy L Thompson 
137ea61e9acSJeremy L Thompson   @param[in] rstr    CeedElemRestriction to restore
138ea61e9acSJeremy L Thompson   @param[in] offsets Array of offset data
139430758c8SJeremy L Thompson 
140430758c8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
141430758c8SJeremy L Thompson 
142430758c8SJeremy L Thompson   @ref User
143430758c8SJeremy L Thompson **/
1442b730f8bSJeremy L Thompson int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr, const CeedInt **offsets) {
145c17ec2beSJeremy L Thompson   if (rstr->rstr_signed) {
146c17ec2beSJeremy L Thompson     CeedCall(CeedElemRestrictionRestoreOffsets(rstr->rstr_signed, offsets));
147c17ec2beSJeremy L Thompson   } else {
148430758c8SJeremy L Thompson     *offsets = NULL;
149d1d35e2fSjeremylt     rstr->num_readers--;
150c17ec2beSJeremy L Thompson   }
151e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
152bd33150aSjeremylt }
153bd33150aSjeremylt 
154bd33150aSjeremylt /**
1553ac43b2cSJeremy L Thompson   @brief Get the strided status of a CeedElemRestriction
1563ac43b2cSJeremy L Thompson 
157ea61e9acSJeremy L Thompson   @param[in]  rstr        CeedElemRestriction
158d1d35e2fSjeremylt   @param[out] is_strided  Variable to store strided status, 1 if strided else 0
1593ac43b2cSJeremy L Thompson 
1603ac43b2cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1613ac43b2cSJeremy L Thompson 
1623ac43b2cSJeremy L Thompson   @ref Backend
1633ac43b2cSJeremy L Thompson **/
164d1d35e2fSjeremylt int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) {
165d1d35e2fSjeremylt   *is_strided = rstr->strides ? true : false;
166e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1673ac43b2cSJeremy L Thompson }
1683ac43b2cSJeremy L Thompson 
1693ac43b2cSJeremy L Thompson /**
170b435c5a6Srezgarshakeri   @brief Get oriented status of a CeedElemRestriction
171b435c5a6Srezgarshakeri 
172ea61e9acSJeremy L Thompson   @param[in]  rstr         CeedElemRestriction
173b435c5a6Srezgarshakeri   @param[out] is_oriented  Variable to store oriented status, 1 if oriented else 0
174b435c5a6Srezgarshakeri 
175b435c5a6Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
176b435c5a6Srezgarshakeri 
177b435c5a6Srezgarshakeri   @ref Backend
178b435c5a6Srezgarshakeri **/
179b435c5a6Srezgarshakeri int CeedElemRestrictionIsOriented(CeedElemRestriction rstr, bool *is_oriented) {
180b435c5a6Srezgarshakeri   *is_oriented = rstr->is_oriented;
181b435c5a6Srezgarshakeri   return CEED_ERROR_SUCCESS;
182b435c5a6Srezgarshakeri }
183b435c5a6Srezgarshakeri 
184b435c5a6Srezgarshakeri /**
185a681ae63Sjeremylt   @brief Get the backend stride status of a CeedElemRestriction
1867a982d89SJeremy L. Thompson 
187ea61e9acSJeremy L Thompson   @param[in]  rstr                 CeedElemRestriction
18896b902e2Sjeremylt   @param[out] has_backend_strides  Variable to store stride status
1897a982d89SJeremy L. Thompson 
1907a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1917a982d89SJeremy L. Thompson 
1927a982d89SJeremy L. Thompson   @ref Backend
1937a982d89SJeremy L. Thompson **/
1942b730f8bSJeremy L Thompson int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, bool *has_backend_strides) {
1956574a04fSJeremy L Thompson   CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
1962b730f8bSJeremy L Thompson   *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
197a681ae63Sjeremylt                           (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
198e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1997a982d89SJeremy L. Thompson }
2007a982d89SJeremy L. Thompson 
2017a982d89SJeremy L. Thompson /**
20249fd234cSJeremy L Thompson 
20349fd234cSJeremy L Thompson   @brief Get the E-vector layout of a CeedElemRestriction
20449fd234cSJeremy L Thompson 
205ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
206ea61e9acSJeremy L Thompson   @param[out] layout  Variable to store layout array, stored as [nodes, components, elements].
207ea61e9acSJeremy L Thompson                         The data for node i, component j, element k in the E-vector is given by i*layout[0] + j*layout[1] + k*layout[2]
20849fd234cSJeremy L Thompson 
20949fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
21049fd234cSJeremy L Thompson 
21149fd234cSJeremy L Thompson   @ref Backend
21249fd234cSJeremy L Thompson **/
2132b730f8bSJeremy L Thompson int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, CeedInt (*layout)[3]) {
2146574a04fSJeremy L Thompson   CeedCheck(rstr->layout[0], rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no layout data");
2152b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*layout)[i] = rstr->layout[i];
216e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
21749fd234cSJeremy L Thompson }
21849fd234cSJeremy L Thompson 
21949fd234cSJeremy L Thompson /**
22049fd234cSJeremy L Thompson 
22149fd234cSJeremy L Thompson   @brief Set the E-vector layout of a CeedElemRestriction
22249fd234cSJeremy L Thompson 
223ea61e9acSJeremy L Thompson   @param[in] rstr   CeedElemRestriction
224ea61e9acSJeremy L Thompson   @param[in] layout Variable to containing layout array, stored as [nodes, components, elements].
225ea61e9acSJeremy L Thompson                       The data for node i, component j, element k in the E-vector is given by i*layout[0] + j*layout[1] + k*layout[2]
22649fd234cSJeremy L Thompson 
22749fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
22849fd234cSJeremy L Thompson 
22949fd234cSJeremy L Thompson   @ref Backend
23049fd234cSJeremy L Thompson **/
2312b730f8bSJeremy L Thompson int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
2322b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) rstr->layout[i] = layout[i];
233e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
23449fd234cSJeremy L Thompson }
23549fd234cSJeremy L Thompson 
23649fd234cSJeremy L Thompson /**
2377a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedElemRestriction
2387a982d89SJeremy L. Thompson 
239ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
2407a982d89SJeremy L. Thompson   @param[out] data Variable to store data
2417a982d89SJeremy L. Thompson 
2427a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2437a982d89SJeremy L. Thompson 
2447a982d89SJeremy L. Thompson   @ref Backend
2457a982d89SJeremy L. Thompson **/
246777ff853SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) {
247777ff853SJeremy L Thompson   *(void **)data = rstr->data;
248e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2497a982d89SJeremy L. Thompson }
2507a982d89SJeremy L. Thompson 
2517a982d89SJeremy L. Thompson /**
2527a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedElemRestriction
2537a982d89SJeremy L. Thompson 
254ea61e9acSJeremy L Thompson   @param[in,out] rstr CeedElemRestriction
255ea61e9acSJeremy L Thompson   @param[in]     data Data to set
2567a982d89SJeremy L. Thompson 
2577a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2587a982d89SJeremy L. Thompson 
2597a982d89SJeremy L. Thompson   @ref Backend
2607a982d89SJeremy L. Thompson **/
261777ff853SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) {
262777ff853SJeremy L Thompson   rstr->data = data;
263e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2647a982d89SJeremy L. Thompson }
2657a982d89SJeremy L. Thompson 
26634359f16Sjeremylt /**
26734359f16Sjeremylt   @brief Increment the reference counter for a CeedElemRestriction
26834359f16Sjeremylt 
269ea61e9acSJeremy L Thompson   @param[in,out] rstr ElemRestriction to increment the reference counter
27034359f16Sjeremylt 
27134359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
27234359f16Sjeremylt 
27334359f16Sjeremylt   @ref Backend
27434359f16Sjeremylt **/
2759560d06aSjeremylt int CeedElemRestrictionReference(CeedElemRestriction rstr) {
27634359f16Sjeremylt   rstr->ref_count++;
27734359f16Sjeremylt   return CEED_ERROR_SUCCESS;
27834359f16Sjeremylt }
27934359f16Sjeremylt 
2806e15d496SJeremy L Thompson /**
2816e15d496SJeremy L Thompson   @brief Estimate number of FLOPs required to apply CeedElemRestriction in t_mode
2826e15d496SJeremy L Thompson 
283ea61e9acSJeremy L Thompson   @param[in]  rstr   ElemRestriction to estimate FLOPs for
284ea61e9acSJeremy L Thompson   @param[in]  t_mode Apply restriction or transpose
285ea61e9acSJeremy L Thompson   @param[out] flops  Address of variable to hold FLOPs estimate
2866e15d496SJeremy L Thompson 
2876e15d496SJeremy L Thompson   @ref Backend
2886e15d496SJeremy L Thompson **/
2892b730f8bSJeremy L Thompson int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedSize *flops) {
2906e15d496SJeremy L Thompson   bool    is_oriented;
2912b730f8bSJeremy L Thompson   CeedInt e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp, scale = 0;
2926e15d496SJeremy L Thompson 
2932b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionIsOriented(rstr, &is_oriented));
2946e15d496SJeremy L Thompson   switch (t_mode) {
2952b730f8bSJeremy L Thompson     case CEED_NOTRANSPOSE:
2962b730f8bSJeremy L Thompson       scale = is_oriented ? 1 : 0;
2972b730f8bSJeremy L Thompson       break;
2982b730f8bSJeremy L Thompson     case CEED_TRANSPOSE:
2992b730f8bSJeremy L Thompson       scale = is_oriented ? 2 : 1;
3002b730f8bSJeremy L Thompson       break;
3016e15d496SJeremy L Thompson   }
3026e15d496SJeremy L Thompson   *flops = e_size * scale;
3036e15d496SJeremy L Thompson 
3046e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3056e15d496SJeremy L Thompson }
3066e15d496SJeremy L Thompson 
3077a982d89SJeremy L. Thompson /// @}
3087a982d89SJeremy L. Thompson 
30915910d16Sjeremylt /// @cond DOXYGEN_SKIP
31015910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
31115910d16Sjeremylt /// @endcond
31215910d16Sjeremylt 
3137a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
3147a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
3157a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
3167a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
317d7b241e6Sjeremylt /// @{
318d7b241e6Sjeremylt 
3197a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
32045f1e315Sjeremylt const CeedInt CEED_STRIDES_BACKEND[3] = {0};
3217a982d89SJeremy L. Thompson 
3224cc79fe7SJed Brown /// Indicate that no CeedElemRestriction is provided by the user
3232b730f8bSJeremy L Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = &ceed_elemrestriction_none;
3247a982d89SJeremy L. Thompson 
325d7b241e6Sjeremylt /**
326b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
327d7b241e6Sjeremylt 
328ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
329ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array
330ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
331ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
332ea61e9acSJeremy L Thompson   @param[in]  comp_stride Stride between components for the same L-vector "node".
333ea61e9acSJeremy L Thompson                             Data for node i, component j, element k can be found in the L-vector at index offsets[i + k*elem_size] + j*comp_stride.
334ea61e9acSJeremy L Thompson   @param[in]  l_size      The size of the L-vector.
335ea61e9acSJeremy L Thompson                             This vector may be larger than the elements and fields given by this restriction.
336ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
337ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
338ea61e9acSJeremy L Thompson   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
339ea61e9acSJeremy L Thompson                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
340ea61e9acSJeremy L Thompson 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
341ea61e9acSJeremy L Thompson   @param[out] rstr    Address of the variable where the newly created CeedElemRestriction will be stored
342d7b241e6Sjeremylt 
343b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
344dfdf5a53Sjeremylt 
3457a982d89SJeremy L. Thompson   @ref User
346b11c1e72Sjeremylt **/
3472b730f8bSJeremy L Thompson int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
3482b730f8bSJeremy L Thompson                               CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
3495fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
3505fe0d4faSjeremylt     Ceed delegate;
3516574a04fSJeremy L Thompson 
3522b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
3536574a04fSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ElemRestrictionCreate");
3542b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
355e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
3565fe0d4faSjeremylt   }
3575fe0d4faSjeremylt 
3586574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
3596574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
3606574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
361e022e1f8SJeremy L Thompson 
3622b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
363*db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
364d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
365d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
366d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
367d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
368d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
369d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
370d1d35e2fSjeremylt   (*rstr)->num_blk     = num_elem;
371d1d35e2fSjeremylt   (*rstr)->blk_size    = 1;
3726402da51SJeremy L Thompson   (*rstr)->is_oriented = false;
3732b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, *rstr));
374e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
375d7b241e6Sjeremylt }
376d7b241e6Sjeremylt 
377d7b241e6Sjeremylt /**
378fc0567d9Srezgarshakeri   @brief Create a CeedElemRestriction with orientation sign
379fc0567d9Srezgarshakeri 
380ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
381ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array
382ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
383ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
384ea61e9acSJeremy L Thompson   @param[in]  comp_stride Stride between components for the same L-vector "node".
385ea61e9acSJeremy L Thompson                             Data for node i, component j, element k can be found in the L-vector at index offsets[i + k*elem_size] + j*comp_stride.
386ea61e9acSJeremy L Thompson   @param[in]  l_size      The size of the L-vector.
387ea61e9acSJeremy L Thompson                             This vector may be larger than the elements and fields given by this restriction.
388ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
389ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
390ea61e9acSJeremy L Thompson   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
391ea61e9acSJeremy L Thompson                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
392ea61e9acSJeremy L Thompson 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
393ea61e9acSJeremy L Thompson   @param[in]  orient      Array of shape [@a num_elem, @a elem_size] with bool false for positively oriented and true to flip the orientation.
394ea61e9acSJeremy L Thompson   @param[out] rstr       Address of the variable where the newly created CeedElemRestriction will be stored
395fc0567d9Srezgarshakeri 
396fc0567d9Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
397fc0567d9Srezgarshakeri 
398fc0567d9Srezgarshakeri   @ref User
399fc0567d9Srezgarshakeri **/
4002b730f8bSJeremy L Thompson int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
4012b730f8bSJeremy L Thompson                                       CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orient,
402fc0567d9Srezgarshakeri                                       CeedElemRestriction *rstr) {
403c7745053SRezgar Shakeri   if (!ceed->ElemRestrictionCreateOriented) {
404fc0567d9Srezgarshakeri     Ceed delegate;
4056574a04fSJeremy L Thompson 
4062b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
4076574a04fSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateOriented");
4082b730f8bSJeremy L Thompson     CeedCall(
4092b730f8bSJeremy L Thompson         CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, orient, rstr));
410fc0567d9Srezgarshakeri     return CEED_ERROR_SUCCESS;
411fc0567d9Srezgarshakeri   }
412fc0567d9Srezgarshakeri 
4136574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
4146574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
4156574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
416e022e1f8SJeremy L Thompson 
4172b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
418*db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
419fc0567d9Srezgarshakeri   (*rstr)->ref_count   = 1;
420fc0567d9Srezgarshakeri   (*rstr)->num_elem    = num_elem;
421fc0567d9Srezgarshakeri   (*rstr)->elem_size   = elem_size;
422fc0567d9Srezgarshakeri   (*rstr)->num_comp    = num_comp;
423fc0567d9Srezgarshakeri   (*rstr)->comp_stride = comp_stride;
424fc0567d9Srezgarshakeri   (*rstr)->l_size      = l_size;
425fc0567d9Srezgarshakeri   (*rstr)->num_blk     = num_elem;
426fc0567d9Srezgarshakeri   (*rstr)->blk_size    = 1;
4276402da51SJeremy L Thompson   (*rstr)->is_oriented = true;
4282b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateOriented(mem_type, copy_mode, offsets, orient, *rstr));
429fc0567d9Srezgarshakeri   return CEED_ERROR_SUCCESS;
430fc0567d9Srezgarshakeri }
431fc0567d9Srezgarshakeri 
432fc0567d9Srezgarshakeri /**
4337509a596Sjeremylt   @brief Create a strided CeedElemRestriction
434d7b241e6Sjeremylt 
435ea61e9acSJeremy L Thompson   @param[in]  ceed      Ceed object where the CeedElemRestriction will be created
436ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
437ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
438ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation "node" (1 for scalar fields)
439ea61e9acSJeremy L Thompson   @param[in]  l_size    The size of the L-vector.
440ea61e9acSJeremy L Thompson                           This vector may be larger than the elements and fields given by this restriction.
441ea61e9acSJeremy L Thompson   @param[in]  strides   Array for strides between [nodes, components, elements].
442ea61e9acSJeremy L Thompson                           Data for node i, component j, element k can be found in the L-vector at index i*strides[0] + j*strides[1] + k*strides[2].
443ea61e9acSJeremy L Thompson                           @a CEED_STRIDES_BACKEND may be used with vectors created by a Ceed backend.
444ea61e9acSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created CeedElemRestriction will be stored
445d7b241e6Sjeremylt 
446b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
447dfdf5a53Sjeremylt 
4487a982d89SJeremy L. Thompson   @ref User
449b11c1e72Sjeremylt **/
4502b730f8bSJeremy L Thompson int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedSize l_size, const CeedInt strides[3],
451f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
4525fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
4535fe0d4faSjeremylt     Ceed delegate;
454b04eb3d9SSebastian Grimberg 
4552b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
4566402da51SJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ElemRestrictionCreateStrided");
4572b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, l_size, strides, rstr));
458e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
4595fe0d4faSjeremylt   }
4605fe0d4faSjeremylt 
4616574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
4626574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
463e022e1f8SJeremy L Thompson 
4642b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
465*db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
466d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
467d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
468d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
469d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
470d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
471d1d35e2fSjeremylt   (*rstr)->num_blk     = num_elem;
472d1d35e2fSjeremylt   (*rstr)->blk_size    = 1;
4736402da51SJeremy L Thompson   (*rstr)->is_oriented = false;
4742b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
4752b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
4762b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, *rstr));
477e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
478d7b241e6Sjeremylt }
479d7b241e6Sjeremylt 
480d7b241e6Sjeremylt /**
481b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
482d7b241e6Sjeremylt 
483ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created.
484ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array.
485ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of unknowns) per element
486ea61e9acSJeremy L Thompson   @param[in]  blk_size    Number of elements in a block
487ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
488ea61e9acSJeremy L Thompson   @param[in]  comp_stride Stride between components for the same L-vector "node".
489ea61e9acSJeremy L Thompson                             Data for node i, component j, element k can be found in the L-vector at index offsets[i + k*elem_size] + j*comp_stride.
490ea61e9acSJeremy L Thompson   @param[in]  l_size      The size of the L-vector.
491ea61e9acSJeremy L Thompson                             This vector may be larger than the elements and fields given by this restriction.
492ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
493ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
494ea61e9acSJeremy L Thompson   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
495ea61e9acSJeremy L Thompson                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
496ea61e9acSJeremy L Thompson  0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1]. The backend will permute and pad this array to the desired ordering for
497ea61e9acSJeremy L Thompson  the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
498ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
499d7b241e6Sjeremylt 
500b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
501dfdf5a53Sjeremylt 
5027a982d89SJeremy L. Thompson   @ref Backend
503b11c1e72Sjeremylt  **/
5042b730f8bSJeremy L Thompson int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedInt comp_stride,
5052b730f8bSJeremy L Thompson                                      CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets,
5064ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
507d1d35e2fSjeremylt   CeedInt *blk_offsets;
508d1d35e2fSjeremylt   CeedInt  num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
509d7b241e6Sjeremylt 
5105fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
5115fe0d4faSjeremylt     Ceed delegate;
5126574a04fSJeremy L Thompson 
5132b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
5146402da51SJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
5152b730f8bSJeremy L Thompson     CeedCall(
5162b730f8bSJeremy L Thompson         CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, blk_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
517e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
5185fe0d4faSjeremylt   }
519d7b241e6Sjeremylt 
5206574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
5216574a04fSJeremy L Thompson   CeedCheck(blk_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
5226574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
5236574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
524e022e1f8SJeremy L Thompson 
5252b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(num_blk * blk_size * elem_size, &blk_offsets));
5262b730f8bSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size, elem_size));
527d7b241e6Sjeremylt 
528*db002c03SJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
529*db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
530d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
531d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
532d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
533d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
534d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
535d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
536d1d35e2fSjeremylt   (*rstr)->num_blk     = num_blk;
537d1d35e2fSjeremylt   (*rstr)->blk_size    = blk_size;
5386402da51SJeremy L Thompson   (*rstr)->is_oriented = false;
5392b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)blk_offsets, *rstr));
540d1d35e2fSjeremylt   if (copy_mode == CEED_OWN_POINTER) {
5412b730f8bSJeremy L Thompson     CeedCall(CeedFree(&offsets));
5421d102b48SJeremy L Thompson   }
543e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
544d7b241e6Sjeremylt }
545d7b241e6Sjeremylt 
546b11c1e72Sjeremylt /**
5477509a596Sjeremylt   @brief Create a blocked strided CeedElemRestriction
5487509a596Sjeremylt 
549ea61e9acSJeremy L Thompson   @param[in]  ceed      Ceed object where the CeedElemRestriction will be created
550ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
551ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
552ea61e9acSJeremy L Thompson   @param[in]  blk_size  Number of elements in a block
553ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation node (1 for scalar fields)
554ea61e9acSJeremy L Thompson   @param[in]  l_size    The size of the L-vector.
555ea61e9acSJeremy L Thompson                           This vector may be larger than the elements and fields given by this restriction.
556ea61e9acSJeremy L Thompson   @param[in]  strides   Array for strides between [nodes, components, elements].
557ea61e9acSJeremy L Thompson                           Data for node i, component j, element k can be found in the L-vector at index i*strides[0] + j*strides[1] + k*strides[2].
558ea61e9acSJeremy L Thompson                           @a CEED_STRIDES_BACKEND may be used with vectors created by a Ceed backend.
559ea61e9acSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created CeedElemRestriction will be stored
5607509a596Sjeremylt 
5617509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
5627509a596Sjeremylt 
5637a982d89SJeremy L. Thompson   @ref User
5647509a596Sjeremylt **/
5652b730f8bSJeremy L Thompson int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedSize l_size,
5668621c6c6SJeremy L Thompson                                             const CeedInt strides[3], CeedElemRestriction *rstr) {
567d1d35e2fSjeremylt   CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
5687509a596Sjeremylt 
5697509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
5707509a596Sjeremylt     Ceed delegate;
5716574a04fSJeremy L Thompson 
5722b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
5736402da51SJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlockedStrided");
5742b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, blk_size, num_comp, l_size, strides, rstr));
575e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
5767509a596Sjeremylt   }
5777509a596Sjeremylt 
5786574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
5796574a04fSJeremy L Thompson   CeedCheck(blk_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
5806574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
581e022e1f8SJeremy L Thompson 
5822b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
583*db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
584d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
585d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
586d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
587d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
588d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
589d1d35e2fSjeremylt   (*rstr)->num_blk     = num_blk;
590d1d35e2fSjeremylt   (*rstr)->blk_size    = blk_size;
5916402da51SJeremy L Thompson   (*rstr)->is_oriented = false;
5922b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
5932b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
5942b730f8bSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, *rstr));
595e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5967509a596Sjeremylt }
5977509a596Sjeremylt 
5987509a596Sjeremylt /**
599c17ec2beSJeremy L Thompson   @brief Copy the pointer to a CeedElemRestriction and set `CeedElemRestrictionApply()` implementation to `CeedElemRestrictionApplyUnsigned()`.
600c17ec2beSJeremy L Thompson 
601c17ec2beSJeremy L Thompson   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
602c17ec2beSJeremy L Thompson 
603c17ec2beSJeremy L Thompson   @param[in]     rstr          CeedElemRestriction to create unsigned reference to
604c17ec2beSJeremy L Thompson   @param[in,out] rstr_unsigned Variable to store unsigned CeedElemRestriction
605c17ec2beSJeremy L Thompson 
606c17ec2beSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
607c17ec2beSJeremy L Thompson 
608c17ec2beSJeremy L Thompson   @ref User
609c17ec2beSJeremy L Thompson **/
610c17ec2beSJeremy L Thompson int CeedElemRestrictionCreateUnsignedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unsigned) {
611c17ec2beSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr_unsigned));
612c17ec2beSJeremy L Thompson 
613c17ec2beSJeremy L Thompson   // Copy old rstr
614c17ec2beSJeremy L Thompson   memcpy(*rstr_unsigned, rstr, sizeof(struct CeedElemRestriction_private));
615c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ceed = NULL;
616c17ec2beSJeremy L Thompson   CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unsigned)->ceed));
617c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ref_count = 1;
618c17ec2beSJeremy L Thompson   (*rstr_unsigned)->strides   = NULL;
619c17ec2beSJeremy L Thompson   if (rstr->strides) {
620c17ec2beSJeremy L Thompson     CeedCall(CeedMalloc(3, &(*rstr_unsigned)->strides));
621c17ec2beSJeremy L Thompson     for (CeedInt i = 0; i < 3; i++) (*rstr_unsigned)->strides[i] = rstr->strides[i];
622c17ec2beSJeremy L Thompson   }
623c17ec2beSJeremy L Thompson   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unsigned)->rstr_signed));
624c17ec2beSJeremy L Thompson 
625c17ec2beSJeremy L Thompson   // Override Apply
626c17ec2beSJeremy L Thompson   (*rstr_unsigned)->Apply = rstr->ApplyUnsigned;
627c17ec2beSJeremy L Thompson 
628c17ec2beSJeremy L Thompson   return CEED_ERROR_SUCCESS;
629c17ec2beSJeremy L Thompson }
630c17ec2beSJeremy L Thompson 
631c17ec2beSJeremy L Thompson /**
632ea61e9acSJeremy L Thompson   @brief Copy the pointer to a CeedElemRestriction.
6339fd66db6SSebastian Grimberg 
634ea61e9acSJeremy L Thompson   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
6359560d06aSjeremylt 
6369fd66db6SSebastian Grimberg   Note: If the value of `rstr_copy` passed into this function is non-NULL, then it is assumed that `rstr_copy` is a pointer to a CeedElemRestriction.
6379fd66db6SSebastian Grimberg         This CeedElemRestriction will be destroyed if `rstr_copy` is the only reference to this CeedElemRestriction.
638ea61e9acSJeremy L Thompson 
639ea61e9acSJeremy L Thompson   @param[in]     rstr      CeedElemRestriction to copy reference to
640ea61e9acSJeremy L Thompson   @param[in,out] rstr_copy Variable to store copied reference
6419560d06aSjeremylt 
6429560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
6439560d06aSjeremylt 
6449560d06aSjeremylt   @ref User
6459560d06aSjeremylt **/
6462b730f8bSJeremy L Thompson int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_copy) {
647393ac2cdSJeremy L Thompson   if (rstr != CEED_ELEMRESTRICTION_NONE) CeedCall(CeedElemRestrictionReference(rstr));
6482b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionDestroy(rstr_copy));
6499560d06aSjeremylt   *rstr_copy = rstr;
6509560d06aSjeremylt   return CEED_ERROR_SUCCESS;
6519560d06aSjeremylt }
6529560d06aSjeremylt 
6539560d06aSjeremylt /**
654b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
655b11c1e72Sjeremylt 
656ea61e9acSJeremy L Thompson   @param[in]  rstr  CeedElemRestriction
657ea61e9acSJeremy L Thompson   @param[out] l_vec The address of the L-vector to be created, or NULL
658ea61e9acSJeremy L Thompson   @param[out] e_vec The address of the E-vector to be created, or NULL
659b11c1e72Sjeremylt 
660b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
661dfdf5a53Sjeremylt 
6627a982d89SJeremy L. Thompson   @ref User
663b11c1e72Sjeremylt **/
6642b730f8bSJeremy L Thompson int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, CeedVector *e_vec) {
665d2643443SJeremy L Thompson   CeedSize e_size, l_size;
666d1d35e2fSjeremylt   l_size = rstr->l_size;
667d1d35e2fSjeremylt   e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
6682b730f8bSJeremy L Thompson   if (l_vec) CeedCall(CeedVectorCreate(rstr->ceed, l_size, l_vec));
6692b730f8bSJeremy L Thompson   if (e_vec) CeedCall(CeedVectorCreate(rstr->ceed, e_size, e_vec));
670e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
671d7b241e6Sjeremylt }
672d7b241e6Sjeremylt 
673d7b241e6Sjeremylt /**
674d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
675d7b241e6Sjeremylt 
676ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
677ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
678ea61e9acSJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
679ea61e9acSJeremy L Thompson   @param[out] ru      Output vector (of shape [@a num_elem * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
680ea61e9acSJeremy L Thompson                         Ordering of the e-vector is decided by the backend.
681ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
682b11c1e72Sjeremylt 
683b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
684dfdf5a53Sjeremylt 
6857a982d89SJeremy L. Thompson   @ref User
686b11c1e72Sjeremylt **/
6872b730f8bSJeremy L Thompson int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
688d7b241e6Sjeremylt   CeedInt m, n;
689d7b241e6Sjeremylt 
690d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
691d1d35e2fSjeremylt     m = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
692d1d35e2fSjeremylt     n = rstr->l_size;
693d7b241e6Sjeremylt   } else {
694d1d35e2fSjeremylt     m = rstr->l_size;
695d1d35e2fSjeremylt     n = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
696d7b241e6Sjeremylt   }
6976574a04fSJeremy L Thompson   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
6986574a04fSJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
6996574a04fSJeremy L Thompson   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
7006574a04fSJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
7012b730f8bSJeremy L Thompson   if (rstr->num_elem > 0) CeedCall(rstr->Apply(rstr, t_mode, u, ru, request));
702e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
703d7b241e6Sjeremylt }
704d7b241e6Sjeremylt 
705d7b241e6Sjeremylt /**
706d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
707be9261b7Sjeremylt 
708ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
709ea61e9acSJeremy L Thompson   @param[in]  block   Block number to restrict to/from, i.e. block=0 will handle elements [0 : blk_size] and block=3 will handle elements [3*blk_size
710ea61e9acSJeremy L Thompson : 4*blk_size]
711ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
712ea61e9acSJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
713ea61e9acSJeremy L Thompson   @param[out] ru      Output vector (of shape [@a blk_size * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
714ea61e9acSJeremy L Thompson                         Ordering of the e-vector is decided by the backend.
715ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
716be9261b7Sjeremylt 
717be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
718be9261b7Sjeremylt 
7197a982d89SJeremy L. Thompson   @ref Backend
720be9261b7Sjeremylt **/
7212b730f8bSJeremy L Thompson int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
7222b730f8bSJeremy L Thompson                                   CeedRequest *request) {
723be9261b7Sjeremylt   CeedInt m, n;
724be9261b7Sjeremylt 
7256402da51SJeremy L Thompson   CeedCheck(rstr->ApplyBlock, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionApplyBlock");
7266402da51SJeremy L Thompson 
727d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
728d1d35e2fSjeremylt     m = rstr->blk_size * rstr->elem_size * rstr->num_comp;
729d1d35e2fSjeremylt     n = rstr->l_size;
730be9261b7Sjeremylt   } else {
731d1d35e2fSjeremylt     m = rstr->l_size;
732d1d35e2fSjeremylt     n = rstr->blk_size * rstr->elem_size * rstr->num_comp;
733be9261b7Sjeremylt   }
7346574a04fSJeremy L Thompson   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
7356574a04fSJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
7366574a04fSJeremy L Thompson   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
7376574a04fSJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
7386574a04fSJeremy L Thompson   CeedCheck(rstr->blk_size * block <= rstr->num_elem, rstr->ceed, CEED_ERROR_DIMENSION,
7396574a04fSJeremy L Thompson             "Cannot retrieve block %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", block, rstr->blk_size * block,
7406574a04fSJeremy L Thompson             rstr->num_elem);
7412b730f8bSJeremy L Thompson   CeedCall(rstr->ApplyBlock(rstr, block, t_mode, u, ru, request));
742e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
743be9261b7Sjeremylt }
744be9261b7Sjeremylt 
745be9261b7Sjeremylt /**
746b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedElemRestriction
747b7c9bbdaSJeremy L Thompson 
748ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
749b7c9bbdaSJeremy L Thompson   @param[out] ceed Variable to store Ceed
750b7c9bbdaSJeremy L Thompson 
751b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
752b7c9bbdaSJeremy L Thompson 
753b7c9bbdaSJeremy L Thompson   @ref Advanced
754b7c9bbdaSJeremy L Thompson **/
755b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
756b7c9bbdaSJeremy L Thompson   *ceed = rstr->ceed;
757b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
758b7c9bbdaSJeremy L Thompson }
759b7c9bbdaSJeremy L Thompson 
760b7c9bbdaSJeremy L Thompson /**
761d979a051Sjeremylt   @brief Get the L-vector component stride
762a681ae63Sjeremylt 
763ea61e9acSJeremy L Thompson   @param[in]  rstr        CeedElemRestriction
764d1d35e2fSjeremylt   @param[out] comp_stride Variable to store component stride
765a681ae63Sjeremylt 
766a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
767a681ae63Sjeremylt 
768b7c9bbdaSJeremy L Thompson   @ref Advanced
769a681ae63Sjeremylt **/
7702b730f8bSJeremy L Thompson int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, CeedInt *comp_stride) {
771d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
772e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
773a681ae63Sjeremylt }
774a681ae63Sjeremylt 
775a681ae63Sjeremylt /**
776a681ae63Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
777a681ae63Sjeremylt 
778ea61e9acSJeremy L Thompson   @param[in] rstr      CeedElemRestriction
779d1d35e2fSjeremylt   @param[out] num_elem Variable to store number of elements
780a681ae63Sjeremylt 
781a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
782a681ae63Sjeremylt 
783b7c9bbdaSJeremy L Thompson   @ref Advanced
784a681ae63Sjeremylt **/
7852b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, CeedInt *num_elem) {
786d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
787e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
788a681ae63Sjeremylt }
789a681ae63Sjeremylt 
790a681ae63Sjeremylt /**
791a681ae63Sjeremylt   @brief Get the size of elements in the CeedElemRestriction
792a681ae63Sjeremylt 
793ea61e9acSJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
794d1d35e2fSjeremylt   @param[out] elem_size Variable to store size of elements
795a681ae63Sjeremylt 
796a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
797a681ae63Sjeremylt 
798b7c9bbdaSJeremy L Thompson   @ref Advanced
799a681ae63Sjeremylt **/
8002b730f8bSJeremy L Thompson int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, CeedInt *elem_size) {
801d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
802e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
803a681ae63Sjeremylt }
804a681ae63Sjeremylt 
805a681ae63Sjeremylt /**
806d979a051Sjeremylt   @brief Get the size of the l-vector for a CeedElemRestriction
807a681ae63Sjeremylt 
808ea61e9acSJeremy L Thompson   @param[in]  rstr   CeedElemRestriction
809d1d35e2fSjeremylt   @param[out] l_size Variable to store number of nodes
810a681ae63Sjeremylt 
811a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
812a681ae63Sjeremylt 
813b7c9bbdaSJeremy L Thompson   @ref Advanced
814a681ae63Sjeremylt **/
8152b730f8bSJeremy L Thompson int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, CeedSize *l_size) {
816d1d35e2fSjeremylt   *l_size = rstr->l_size;
817e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
818a681ae63Sjeremylt }
819a681ae63Sjeremylt 
820a681ae63Sjeremylt /**
821ea61e9acSJeremy L Thompson   @brief Get the number of components in the elements of a CeedElemRestriction
822a681ae63Sjeremylt 
823ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction
824d1d35e2fSjeremylt   @param[out] num_comp Variable to store number of components
825a681ae63Sjeremylt 
826a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
827a681ae63Sjeremylt 
828b7c9bbdaSJeremy L Thompson   @ref Advanced
829a681ae63Sjeremylt **/
8302b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, CeedInt *num_comp) {
831d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
832e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
833a681ae63Sjeremylt }
834a681ae63Sjeremylt 
835a681ae63Sjeremylt /**
836a681ae63Sjeremylt   @brief Get the number of blocks in a CeedElemRestriction
837a681ae63Sjeremylt 
838ea61e9acSJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
839d1d35e2fSjeremylt   @param[out] num_block Variable to store number of blocks
840a681ae63Sjeremylt 
841a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
842a681ae63Sjeremylt 
843b7c9bbdaSJeremy L Thompson   @ref Advanced
844a681ae63Sjeremylt **/
8452b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, CeedInt *num_block) {
846d1d35e2fSjeremylt   *num_block = rstr->num_blk;
847e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
848a681ae63Sjeremylt }
849a681ae63Sjeremylt 
850a681ae63Sjeremylt /**
851a681ae63Sjeremylt   @brief Get the size of blocks in the CeedElemRestriction
852a681ae63Sjeremylt 
853ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction
854d1d35e2fSjeremylt   @param[out] blk_size Variable to store size of blocks
855a681ae63Sjeremylt 
856a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
857a681ae63Sjeremylt 
858b7c9bbdaSJeremy L Thompson   @ref Advanced
859a681ae63Sjeremylt **/
8602b730f8bSJeremy L Thompson int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, CeedInt *blk_size) {
861d1d35e2fSjeremylt   *blk_size = rstr->blk_size;
862e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
863a681ae63Sjeremylt }
864a681ae63Sjeremylt 
865a681ae63Sjeremylt /**
866d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
8671469ee4dSjeremylt 
868ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
869d1d35e2fSjeremylt   @param[out] mult Vector to store multiplicity (of size l_size)
8701469ee4dSjeremylt 
8711469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
8721469ee4dSjeremylt 
8737a982d89SJeremy L. Thompson   @ref User
8741469ee4dSjeremylt **/
8752b730f8bSJeremy L Thompson int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, CeedVector mult) {
876d1d35e2fSjeremylt   CeedVector e_vec;
8771469ee4dSjeremylt 
87825509ebbSRezgar Shakeri   // Create e_vec to hold intermediate computation in E^T (E 1)
8792b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionCreateVector(rstr, NULL, &e_vec));
8801469ee4dSjeremylt 
88125509ebbSRezgar Shakeri   // Compute e_vec = E * 1
8822b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 1.0));
8832b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, CEED_REQUEST_IMMEDIATE));
88425509ebbSRezgar Shakeri   // Compute multiplicity, mult = E^T * e_vec = E^T (E 1)
8852b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 0.0));
8862b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, CEED_REQUEST_IMMEDIATE));
8871469ee4dSjeremylt   // Cleanup
8882b730f8bSJeremy L Thompson   CeedCall(CeedVectorDestroy(&e_vec));
889e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
8901469ee4dSjeremylt }
8911469ee4dSjeremylt 
8921469ee4dSjeremylt /**
893f02ca4a2SJed Brown   @brief View a CeedElemRestriction
894f02ca4a2SJed Brown 
895f02ca4a2SJed Brown   @param[in] rstr   CeedElemRestriction to view
896f02ca4a2SJed Brown   @param[in] stream Stream to write; typically stdout/stderr or a file
897f02ca4a2SJed Brown 
898f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
899f02ca4a2SJed Brown 
9007a982d89SJeremy L. Thompson   @ref User
901f02ca4a2SJed Brown **/
902f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
9037509a596Sjeremylt   char stridesstr[500];
9042b730f8bSJeremy L Thompson   if (rstr->strides) {
9052b730f8bSJeremy L Thompson     sprintf(stridesstr, "[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "]", rstr->strides[0], rstr->strides[1], rstr->strides[2]);
9062b730f8bSJeremy L Thompson   } else {
907990fdeb6SJeremy L Thompson     sprintf(stridesstr, "%" CeedInt_FMT, rstr->comp_stride);
9082b730f8bSJeremy L Thompson   }
9097509a596Sjeremylt 
9102b730f8bSJeremy L Thompson   fprintf(stream, "%sCeedElemRestriction from (%td, %" CeedInt_FMT ") to %" CeedInt_FMT " elements with %" CeedInt_FMT " nodes each and %s %s\n",
9112b730f8bSJeremy L Thompson           rstr->blk_size > 1 ? "Blocked " : "", rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
912d979a051Sjeremylt           rstr->strides ? "strides" : "component stride", stridesstr);
913e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
914f02ca4a2SJed Brown }
915f02ca4a2SJed Brown 
916f02ca4a2SJed Brown /**
917b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
918b11c1e72Sjeremylt 
919ea61e9acSJeremy L Thompson   @param[in,out] rstr CeedElemRestriction to destroy
920b11c1e72Sjeremylt 
921b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
922dfdf5a53Sjeremylt 
9237a982d89SJeremy L. Thompson   @ref User
924b11c1e72Sjeremylt **/
9254ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
926393ac2cdSJeremy L Thompson   if (!*rstr || *rstr == CEED_ELEMRESTRICTION_NONE || --(*rstr)->ref_count > 0) {
927ad6481ceSJeremy L Thompson     *rstr = NULL;
928ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
929ad6481ceSJeremy L Thompson   }
9306574a04fSJeremy L Thompson   CeedCheck((*rstr)->num_readers == 0, (*rstr)->ceed, CEED_ERROR_ACCESS,
9316574a04fSJeremy L Thompson             "Cannot destroy CeedElemRestriction, a process has read access to the offset data");
932c17ec2beSJeremy L Thompson 
933c17ec2beSJeremy L Thompson   // Only destroy backend data once between rstr and unsigned copy
934c17ec2beSJeremy L Thompson   if ((*rstr)->rstr_signed) CeedCall(CeedElemRestrictionDestroy(&(*rstr)->rstr_signed));
935c17ec2beSJeremy L Thompson   else if ((*rstr)->Destroy) CeedCall((*rstr)->Destroy(*rstr));
936c17ec2beSJeremy L Thompson 
9372b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*rstr)->strides));
9382b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*rstr)->ceed));
9392b730f8bSJeremy L Thompson   CeedCall(CeedFree(rstr));
940e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
941d7b241e6Sjeremylt }
942d7b241e6Sjeremylt 
943d7b241e6Sjeremylt /// @}
944