xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-elemrestriction.c (revision 0c73c0392b237e966a4ce5108053a931350d7505)
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 
27fcbe8c06SSebastian Grimberg   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
28*0c73c039SSebastian Grimberg   @param[out] blk_offsets Array of permuted and padded array values of shape [@a num_blk, @a elem_size, @a blk_size].
29ea61e9acSJeremy L Thompson   @param[in]  num_blk     Number of blocks
30ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements
31ea61e9acSJeremy L Thompson   @param[in]  blk_size    Number of elements in a block
32ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size of each element
337a982d89SJeremy L. Thompson 
347a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
357a982d89SJeremy L. Thompson 
367a982d89SJeremy L. Thompson   @ref Utility
377a982d89SJeremy L. Thompson **/
382b730f8bSJeremy L Thompson int CeedPermutePadOffsets(const CeedInt *offsets, CeedInt *blk_offsets, CeedInt num_blk, CeedInt num_elem, CeedInt blk_size, CeedInt elem_size) {
392b730f8bSJeremy L Thompson   for (CeedInt e = 0; e < num_blk * blk_size; e += blk_size) {
402b730f8bSJeremy L Thompson     for (CeedInt j = 0; j < blk_size; j++) {
412b730f8bSJeremy L Thompson       for (CeedInt k = 0; k < elem_size; k++) {
422b730f8bSJeremy L Thompson         blk_offsets[e * elem_size + k * blk_size + j] = offsets[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
432b730f8bSJeremy L Thompson       }
442b730f8bSJeremy L Thompson     }
452b730f8bSJeremy L Thompson   }
46e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
477a982d89SJeremy L. Thompson }
487a982d89SJeremy L. Thompson 
4977d1c127SSebastian Grimberg /**
5077d1c127SSebastian Grimberg   @brief Permute and pad orientations for a blocked restriction
5177d1c127SSebastian Grimberg 
52fcbe8c06SSebastian Grimberg   @param[in]  orients     Array of shape [@a num_elem, @a elem_size].
53*0c73c039SSebastian Grimberg   @param[out] blk_orients Array of permuted and padded array values of shape [@a num_blk, @a elem_size, @a blk_size].
5477d1c127SSebastian Grimberg   @param[in]  num_blk     Number of blocks
5577d1c127SSebastian Grimberg   @param[in]  num_elem    Number of elements
5677d1c127SSebastian Grimberg   @param[in]  blk_size    Number of elements in a block
5777d1c127SSebastian Grimberg   @param[in]  elem_size   Size of each element
5877d1c127SSebastian Grimberg 
5977d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
6077d1c127SSebastian Grimberg 
6177d1c127SSebastian Grimberg   @ref Utility
6277d1c127SSebastian Grimberg **/
63*0c73c039SSebastian Grimberg int CeedPermutePadOrients(const bool *orients, bool *blk_orients, CeedInt num_blk, CeedInt num_elem, CeedInt blk_size, CeedInt elem_size) {
6477d1c127SSebastian Grimberg   for (CeedInt e = 0; e < num_blk * blk_size; e += blk_size) {
6577d1c127SSebastian Grimberg     for (CeedInt j = 0; j < blk_size; j++) {
6677d1c127SSebastian Grimberg       for (CeedInt k = 0; k < elem_size; k++) {
6777d1c127SSebastian Grimberg         blk_orients[e * elem_size + k * blk_size + j] = orients[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
6877d1c127SSebastian Grimberg       }
6977d1c127SSebastian Grimberg     }
7077d1c127SSebastian Grimberg   }
7177d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
7277d1c127SSebastian Grimberg }
7377d1c127SSebastian Grimberg 
74*0c73c039SSebastian Grimberg /**
75*0c73c039SSebastian Grimberg   @brief Permute and pad curl-conforming orientations for a blocked restriction
76*0c73c039SSebastian Grimberg 
77*0c73c039SSebastian Grimberg   @param[in]  curl_orients     Array of shape [@a num_elem, @a 3 * elem_size].
78*0c73c039SSebastian Grimberg   @param[out] blk_curl_orients Array of permuted and padded array values of shape [@a num_blk, @a elem_size, @a blk_size].
79*0c73c039SSebastian Grimberg   @param[in]  num_blk          Number of blocks
80*0c73c039SSebastian Grimberg   @param[in]  num_elem         Number of elements
81*0c73c039SSebastian Grimberg   @param[in]  blk_size         Number of elements in a block
82*0c73c039SSebastian Grimberg   @param[in]  elem_size        Size of each element
83*0c73c039SSebastian Grimberg 
84*0c73c039SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
85*0c73c039SSebastian Grimberg 
86*0c73c039SSebastian Grimberg   @ref Utility
87*0c73c039SSebastian Grimberg **/
88*0c73c039SSebastian Grimberg int CeedPermutePadCurlOrients(const CeedInt8 *curl_orients, CeedInt8 *blk_curl_orients, CeedInt num_blk, CeedInt num_elem, CeedInt blk_size,
89*0c73c039SSebastian Grimberg                               CeedInt elem_size) {
90*0c73c039SSebastian Grimberg   for (CeedInt e = 0; e < num_blk * blk_size; e += blk_size) {
91*0c73c039SSebastian Grimberg     for (CeedInt j = 0; j < blk_size; j++) {
92*0c73c039SSebastian Grimberg       for (CeedInt k = 0; k < elem_size; k++) {
93*0c73c039SSebastian Grimberg         blk_curl_orients[e * elem_size + k * blk_size + j] = curl_orients[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
94*0c73c039SSebastian Grimberg       }
95*0c73c039SSebastian Grimberg     }
96*0c73c039SSebastian Grimberg   }
97*0c73c039SSebastian Grimberg   return CEED_ERROR_SUCCESS;
98*0c73c039SSebastian Grimberg }
99*0c73c039SSebastian Grimberg 
1007a982d89SJeremy L. Thompson /// @}
1017a982d89SJeremy L. Thompson 
1027a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1037a982d89SJeremy L. Thompson /// CeedElemRestriction Backend API
1047a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1057a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionBackend
1067a982d89SJeremy L. Thompson /// @{
1077a982d89SJeremy L. Thompson 
1087a982d89SJeremy L. Thompson /**
10978b2e752SJeremy L Thompson   @brief Restrict an L-vector to an E-vector or apply its transpose ignoring any
11078b2e752SJeremy L Thompson          provided orientations
11178b2e752SJeremy L Thompson 
11278b2e752SJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
11378b2e752SJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
11478b2e752SJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
11578b2e752SJeremy L Thompson   @param[out] ru      Output vector (of shape [@a num_elem * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
11678b2e752SJeremy L Thompson                         Ordering of the e-vector is decided by the backend.
11778b2e752SJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
11878b2e752SJeremy L Thompson 
11978b2e752SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
12078b2e752SJeremy L Thompson 
12178b2e752SJeremy L Thompson   @ref User
12278b2e752SJeremy L Thompson **/
12378b2e752SJeremy L Thompson int CeedElemRestrictionApplyUnsigned(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
12478b2e752SJeremy L Thompson   CeedInt m, n;
12578b2e752SJeremy L Thompson 
12678b2e752SJeremy L Thompson   CeedCheck(rstr->ApplyUnsigned, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ElemRestrictionApplyUnsigned");
12778b2e752SJeremy L Thompson 
12878b2e752SJeremy L Thompson   if (t_mode == CEED_NOTRANSPOSE) {
12978b2e752SJeremy L Thompson     m = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
13078b2e752SJeremy L Thompson     n = rstr->l_size;
13178b2e752SJeremy L Thompson   } else {
13278b2e752SJeremy L Thompson     m = rstr->l_size;
13378b2e752SJeremy L Thompson     n = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
13478b2e752SJeremy L Thompson   }
13578b2e752SJeremy L Thompson   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
13678b2e752SJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
13778b2e752SJeremy L Thompson   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
13878b2e752SJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
13978b2e752SJeremy L Thompson   if (rstr->num_elem > 0) CeedCall(rstr->ApplyUnsigned(rstr, t_mode, u, ru, request));
14077d1c127SSebastian Grimberg 
14178b2e752SJeremy L Thompson   return CEED_ERROR_SUCCESS;
14278b2e752SJeremy L Thompson }
14378b2e752SJeremy L Thompson 
14478b2e752SJeremy L Thompson /**
145fcbe8c06SSebastian Grimberg   @brief Get the type of a CeedElemRestriction
146a681ae63Sjeremylt 
147fcbe8c06SSebastian Grimberg   @param[in]  rstr      CeedElemRestriction
148fcbe8c06SSebastian Grimberg   @param[out] rstr_type Variable to store restriction type
149fcbe8c06SSebastian Grimberg 
150fcbe8c06SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
151fcbe8c06SSebastian Grimberg 
152fcbe8c06SSebastian Grimberg   @ref Backend
153fcbe8c06SSebastian Grimberg **/
154fcbe8c06SSebastian Grimberg int CeedElemRestrictionGetType(CeedElemRestriction rstr, CeedRestrictionType *rstr_type) {
155fcbe8c06SSebastian Grimberg   *rstr_type = rstr->rstr_type;
156fcbe8c06SSebastian Grimberg   return CEED_ERROR_SUCCESS;
157fcbe8c06SSebastian Grimberg }
158fcbe8c06SSebastian Grimberg 
159fcbe8c06SSebastian Grimberg /**
160fcbe8c06SSebastian Grimberg   @brief Get the strided status of a CeedElemRestriction
161fcbe8c06SSebastian Grimberg 
162fcbe8c06SSebastian Grimberg   @param[in]  rstr       CeedElemRestriction
163fcbe8c06SSebastian Grimberg   @param[out] is_strided Variable to store strided status, 1 if strided else 0
164fcbe8c06SSebastian Grimberg **/
165fcbe8c06SSebastian Grimberg int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) {
166fcbe8c06SSebastian Grimberg   *is_strided = (rstr->rstr_type == CEED_RESTRICTION_STRIDED);
167fcbe8c06SSebastian Grimberg   return CEED_ERROR_SUCCESS;
168fcbe8c06SSebastian Grimberg }
169fcbe8c06SSebastian Grimberg 
170fcbe8c06SSebastian Grimberg /**
171a681ae63Sjeremylt   @brief Get the strides of a strided CeedElemRestriction
1727a982d89SJeremy L. Thompson 
173ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
174a681ae63Sjeremylt   @param[out] strides Variable to store strides array
1757a982d89SJeremy L. Thompson 
1767a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1777a982d89SJeremy L. Thompson 
1787a982d89SJeremy L. Thompson   @ref Backend
1797a982d89SJeremy L. Thompson **/
1802b730f8bSJeremy L Thompson int CeedElemRestrictionGetStrides(CeedElemRestriction rstr, CeedInt (*strides)[3]) {
1816574a04fSJeremy L Thompson   CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
1822b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*strides)[i] = rstr->strides[i];
183e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1847a982d89SJeremy L. Thompson }
1857a982d89SJeremy L. Thompson 
1867a982d89SJeremy L. Thompson /**
18777d1c127SSebastian Grimberg   @brief Get the backend stride status of a CeedElemRestriction
18877d1c127SSebastian Grimberg 
18977d1c127SSebastian Grimberg   @param[in]  rstr                 CeedElemRestriction
19077d1c127SSebastian Grimberg   @param[out] has_backend_strides  Variable to store stride status
19177d1c127SSebastian Grimberg 
19277d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
19377d1c127SSebastian Grimberg 
19477d1c127SSebastian Grimberg   @ref Backend
19577d1c127SSebastian Grimberg **/
19677d1c127SSebastian Grimberg int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, bool *has_backend_strides) {
19777d1c127SSebastian Grimberg   CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
19877d1c127SSebastian Grimberg   *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
19977d1c127SSebastian Grimberg                           (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
20077d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
20177d1c127SSebastian Grimberg }
20277d1c127SSebastian Grimberg 
20377d1c127SSebastian Grimberg /**
204bd33150aSjeremylt   @brief Get read-only access to a CeedElemRestriction offsets array by memtype
205bd33150aSjeremylt 
206ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction to retrieve offsets
207fcbe8c06SSebastian Grimberg   @param[in]  mem_type Memory type on which to access the array.
208fcbe8c06SSebastian Grimberg                          If the backend uses a different memory type, this will perform a copy (possibly cached).
209d1d35e2fSjeremylt   @param[out] offsets  Array on memory type mem_type
210bd33150aSjeremylt 
211bd33150aSjeremylt   @return An error code: 0 - success, otherwise - failure
212bd33150aSjeremylt 
213bd33150aSjeremylt   @ref User
214bd33150aSjeremylt **/
2152b730f8bSJeremy L Thompson int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) {
216c17ec2beSJeremy L Thompson   if (rstr->rstr_signed) {
217c17ec2beSJeremy L Thompson     CeedCall(CeedElemRestrictionGetOffsets(rstr->rstr_signed, mem_type, offsets));
218c17ec2beSJeremy L Thompson   } else {
2196574a04fSJeremy L Thompson     CeedCheck(rstr->GetOffsets, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetOffsets");
2202b730f8bSJeremy L Thompson     CeedCall(rstr->GetOffsets(rstr, mem_type, offsets));
221d1d35e2fSjeremylt     rstr->num_readers++;
222c17ec2beSJeremy L Thompson   }
223e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
224430758c8SJeremy L Thompson }
225430758c8SJeremy L Thompson 
226430758c8SJeremy L Thompson /**
227430758c8SJeremy L Thompson   @brief Restore an offsets array obtained using CeedElemRestrictionGetOffsets()
228430758c8SJeremy L Thompson 
229ea61e9acSJeremy L Thompson   @param[in] rstr    CeedElemRestriction to restore
230ea61e9acSJeremy L Thompson   @param[in] offsets Array of offset data
231430758c8SJeremy L Thompson 
232430758c8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
233430758c8SJeremy L Thompson 
234430758c8SJeremy L Thompson   @ref User
235430758c8SJeremy L Thompson **/
2362b730f8bSJeremy L Thompson int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr, const CeedInt **offsets) {
237c17ec2beSJeremy L Thompson   if (rstr->rstr_signed) {
238c17ec2beSJeremy L Thompson     CeedCall(CeedElemRestrictionRestoreOffsets(rstr->rstr_signed, offsets));
239c17ec2beSJeremy L Thompson   } else {
240430758c8SJeremy L Thompson     *offsets = NULL;
241d1d35e2fSjeremylt     rstr->num_readers--;
242c17ec2beSJeremy L Thompson   }
243e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
244bd33150aSjeremylt }
245bd33150aSjeremylt 
246bd33150aSjeremylt /**
24777d1c127SSebastian Grimberg   @brief Get read-only access to a CeedElemRestriction orientations array by memtype
2483ac43b2cSJeremy L Thompson 
24977d1c127SSebastian Grimberg   @param[in]  rstr     CeedElemRestriction to retrieve orientations
250fcbe8c06SSebastian Grimberg   @param[in]  mem_type Memory type on which to access the array.
251fcbe8c06SSebastian Grimberg                          If the backend uses a different memory type, this will perform a copy (possibly cached).
25277d1c127SSebastian Grimberg   @param[out] orients  Array on memory type mem_type
2533ac43b2cSJeremy L Thompson 
2543ac43b2cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2553ac43b2cSJeremy L Thompson 
25677d1c127SSebastian Grimberg   @ref User
2573ac43b2cSJeremy L Thompson **/
25877d1c127SSebastian Grimberg int CeedElemRestrictionGetOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const bool **orients) {
259fcbe8c06SSebastian Grimberg   CeedCheck(rstr->GetOrientations, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetOrientations");
26077d1c127SSebastian Grimberg   CeedCall(rstr->GetOrientations(rstr, mem_type, orients));
26177d1c127SSebastian Grimberg   rstr->num_readers++;
262e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2633ac43b2cSJeremy L Thompson }
2643ac43b2cSJeremy L Thompson 
2653ac43b2cSJeremy L Thompson /**
26677d1c127SSebastian Grimberg   @brief Restore an orientations array obtained using CeedElemRestrictionGetOrientations()
267b435c5a6Srezgarshakeri 
26877d1c127SSebastian Grimberg   @param[in] rstr    CeedElemRestriction to restore
26977d1c127SSebastian Grimberg   @param[in] orients Array of orientation data
270b435c5a6Srezgarshakeri 
271b435c5a6Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
272b435c5a6Srezgarshakeri 
27377d1c127SSebastian Grimberg   @ref User
274b435c5a6Srezgarshakeri **/
27577d1c127SSebastian Grimberg int CeedElemRestrictionRestoreOrientations(CeedElemRestriction rstr, const bool **orients) {
27677d1c127SSebastian Grimberg   *orients = NULL;
27777d1c127SSebastian Grimberg   rstr->num_readers--;
278b435c5a6Srezgarshakeri   return CEED_ERROR_SUCCESS;
279b435c5a6Srezgarshakeri }
280b435c5a6Srezgarshakeri 
281b435c5a6Srezgarshakeri /**
28277d1c127SSebastian Grimberg   @brief Get read-only access to a CeedElemRestriction curl-conforming orientations array by memtype
2837a982d89SJeremy L. Thompson 
28477d1c127SSebastian Grimberg   @param[in]  rstr         CeedElemRestriction to retrieve curl-conforming orientations
285fcbe8c06SSebastian Grimberg   @param[in]  mem_type     Memory type on which to access the array.
286fcbe8c06SSebastian Grimberg                              If the backend uses a different memory type, this will perform a copy (possibly cached).
28777d1c127SSebastian Grimberg   @param[out] curl_orients Array on memory type mem_type
2887a982d89SJeremy L. Thompson 
2897a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2907a982d89SJeremy L. Thompson 
29177d1c127SSebastian Grimberg   @ref User
2927a982d89SJeremy L. Thompson **/
293*0c73c039SSebastian Grimberg int CeedElemRestrictionGetCurlOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt8 **curl_orients) {
294fcbe8c06SSebastian Grimberg   CeedCheck(rstr->GetCurlOrientations, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetCurlOrientations");
29577d1c127SSebastian Grimberg   CeedCall(rstr->GetCurlOrientations(rstr, mem_type, curl_orients));
29677d1c127SSebastian Grimberg   rstr->num_readers++;
29777d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
29877d1c127SSebastian Grimberg }
29977d1c127SSebastian Grimberg 
30077d1c127SSebastian Grimberg /**
30177d1c127SSebastian Grimberg   @brief Restore an orientations array obtained using CeedElemRestrictionGetCurlOrientations()
30277d1c127SSebastian Grimberg 
30377d1c127SSebastian Grimberg   @param[in] rstr         CeedElemRestriction to restore
30477d1c127SSebastian Grimberg   @param[in] curl_orients Array of orientation data
30577d1c127SSebastian Grimberg 
30677d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
30777d1c127SSebastian Grimberg 
30877d1c127SSebastian Grimberg   @ref User
30977d1c127SSebastian Grimberg **/
310*0c73c039SSebastian Grimberg int CeedElemRestrictionRestoreCurlOrientations(CeedElemRestriction rstr, const CeedInt8 **curl_orients) {
31177d1c127SSebastian Grimberg   *curl_orients = NULL;
31277d1c127SSebastian Grimberg   rstr->num_readers--;
313e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3147a982d89SJeremy L. Thompson }
3157a982d89SJeremy L. Thompson 
3167a982d89SJeremy L. Thompson /**
31749fd234cSJeremy L Thompson 
31849fd234cSJeremy L Thompson   @brief Get the E-vector layout of a CeedElemRestriction
31949fd234cSJeremy L Thompson 
320ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
321fcbe8c06SSebastian Grimberg   @param[out] layout  Variable to store layout array, stored as [nodes, components, elements].
322fcbe8c06SSebastian Grimberg                         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]
32349fd234cSJeremy L Thompson 
32449fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
32549fd234cSJeremy L Thompson 
32649fd234cSJeremy L Thompson   @ref Backend
32749fd234cSJeremy L Thompson **/
3282b730f8bSJeremy L Thompson int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, CeedInt (*layout)[3]) {
3296574a04fSJeremy L Thompson   CeedCheck(rstr->layout[0], rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no layout data");
3302b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*layout)[i] = rstr->layout[i];
331e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
33249fd234cSJeremy L Thompson }
33349fd234cSJeremy L Thompson 
33449fd234cSJeremy L Thompson /**
33549fd234cSJeremy L Thompson 
33649fd234cSJeremy L Thompson   @brief Set the E-vector layout of a CeedElemRestriction
33749fd234cSJeremy L Thompson 
338ea61e9acSJeremy L Thompson   @param[in] rstr   CeedElemRestriction
339ea61e9acSJeremy L Thompson   @param[in] layout Variable to containing layout array, stored as [nodes, components, elements].
340ea61e9acSJeremy 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]
34149fd234cSJeremy L Thompson 
34249fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
34349fd234cSJeremy L Thompson 
34449fd234cSJeremy L Thompson   @ref Backend
34549fd234cSJeremy L Thompson **/
3462b730f8bSJeremy L Thompson int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
3472b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) rstr->layout[i] = layout[i];
348e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
34949fd234cSJeremy L Thompson }
35049fd234cSJeremy L Thompson 
35149fd234cSJeremy L Thompson /**
3527a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedElemRestriction
3537a982d89SJeremy L. Thompson 
354ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
3557a982d89SJeremy L. Thompson   @param[out] data Variable to store data
3567a982d89SJeremy L. Thompson 
3577a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3587a982d89SJeremy L. Thompson 
3597a982d89SJeremy L. Thompson   @ref Backend
3607a982d89SJeremy L. Thompson **/
361777ff853SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) {
362777ff853SJeremy L Thompson   *(void **)data = rstr->data;
363e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3647a982d89SJeremy L. Thompson }
3657a982d89SJeremy L. Thompson 
3667a982d89SJeremy L. Thompson /**
3677a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedElemRestriction
3687a982d89SJeremy L. Thompson 
369ea61e9acSJeremy L Thompson   @param[in,out] rstr CeedElemRestriction
370ea61e9acSJeremy L Thompson   @param[in]     data Data to set
3717a982d89SJeremy L. Thompson 
3727a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3737a982d89SJeremy L. Thompson 
3747a982d89SJeremy L. Thompson   @ref Backend
3757a982d89SJeremy L. Thompson **/
376777ff853SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) {
377777ff853SJeremy L Thompson   rstr->data = data;
378e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3797a982d89SJeremy L. Thompson }
3807a982d89SJeremy L. Thompson 
38134359f16Sjeremylt /**
38234359f16Sjeremylt   @brief Increment the reference counter for a CeedElemRestriction
38334359f16Sjeremylt 
384ea61e9acSJeremy L Thompson   @param[in,out] rstr ElemRestriction to increment the reference counter
38534359f16Sjeremylt 
38634359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
38734359f16Sjeremylt 
38834359f16Sjeremylt   @ref Backend
38934359f16Sjeremylt **/
3909560d06aSjeremylt int CeedElemRestrictionReference(CeedElemRestriction rstr) {
39134359f16Sjeremylt   rstr->ref_count++;
39234359f16Sjeremylt   return CEED_ERROR_SUCCESS;
39334359f16Sjeremylt }
39434359f16Sjeremylt 
3956e15d496SJeremy L Thompson /**
3966e15d496SJeremy L Thompson   @brief Estimate number of FLOPs required to apply CeedElemRestriction in t_mode
3976e15d496SJeremy L Thompson 
398ea61e9acSJeremy L Thompson   @param[in]  rstr   ElemRestriction to estimate FLOPs for
399ea61e9acSJeremy L Thompson   @param[in]  t_mode Apply restriction or transpose
400ea61e9acSJeremy L Thompson   @param[out] flops  Address of variable to hold FLOPs estimate
4016e15d496SJeremy L Thompson 
4026e15d496SJeremy L Thompson   @ref Backend
4036e15d496SJeremy L Thompson **/
4042b730f8bSJeremy L Thompson int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedSize *flops) {
40577d1c127SSebastian Grimberg   const bool     *orients      = NULL;
406*0c73c039SSebastian Grimberg   const CeedInt8 *curl_orients = NULL;
4072b730f8bSJeremy L Thompson   CeedInt         e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp, scale = 0;
4086e15d496SJeremy L Thompson 
40977d1c127SSebastian Grimberg   CeedCall(CeedElemRestrictionGetOrientations(rstr, CEED_MEM_HOST, &orients));
41077d1c127SSebastian Grimberg   CeedCall(CeedElemRestrictionGetCurlOrientations(rstr, CEED_MEM_HOST, &curl_orients));
41177d1c127SSebastian Grimberg   if (t_mode == CEED_TRANSPOSE) {
41277d1c127SSebastian Grimberg     if (!orients && !curl_orients) {
41377d1c127SSebastian Grimberg       scale = 1;
41477d1c127SSebastian Grimberg     } else if (!curl_orients) {
41577d1c127SSebastian Grimberg       scale = 2;
41677d1c127SSebastian Grimberg     } else {
41777d1c127SSebastian Grimberg       scale = 6;
4186e15d496SJeremy L Thompson     }
41977d1c127SSebastian Grimberg   } else {
42077d1c127SSebastian Grimberg     if (!orients && !curl_orients) {
42177d1c127SSebastian Grimberg       scale = 0;
42277d1c127SSebastian Grimberg     } else if (!curl_orients) {
42377d1c127SSebastian Grimberg       scale = 1;
42477d1c127SSebastian Grimberg     } else {
42577d1c127SSebastian Grimberg       scale = 5;
42677d1c127SSebastian Grimberg     }
42777d1c127SSebastian Grimberg   }
42877d1c127SSebastian Grimberg   CeedCall(CeedElemRestrictionRestoreOrientations(rstr, &orients));
42977d1c127SSebastian Grimberg   CeedCall(CeedElemRestrictionRestoreCurlOrientations(rstr, &curl_orients));
4306e15d496SJeremy L Thompson   *flops = e_size * scale;
4316e15d496SJeremy L Thompson 
4326e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4336e15d496SJeremy L Thompson }
4346e15d496SJeremy L Thompson 
4357a982d89SJeremy L. Thompson /// @}
4367a982d89SJeremy L. Thompson 
43715910d16Sjeremylt /// @cond DOXYGEN_SKIP
43815910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
43915910d16Sjeremylt /// @endcond
44015910d16Sjeremylt 
4417a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
4427a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
4437a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
4447a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
445d7b241e6Sjeremylt /// @{
446d7b241e6Sjeremylt 
4477a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
44845f1e315Sjeremylt const CeedInt CEED_STRIDES_BACKEND[3] = {0};
4497a982d89SJeremy L. Thompson 
4504cc79fe7SJed Brown /// Indicate that no CeedElemRestriction is provided by the user
4512b730f8bSJeremy L Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = &ceed_elemrestriction_none;
4527a982d89SJeremy L. Thompson 
453d7b241e6Sjeremylt /**
454b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
455d7b241e6Sjeremylt 
456ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
457ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array
458ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
459ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
460fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
461fcbe8c06SSebastian Grimberg                             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.
462fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
463fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
464ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
465ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
466fcbe8c06SSebastian Grimberg   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
467fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
468fcbe8c06SSebastian Grimberg 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
469ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
470d7b241e6Sjeremylt 
471b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
472dfdf5a53Sjeremylt 
4737a982d89SJeremy L. Thompson   @ref User
474b11c1e72Sjeremylt **/
4752b730f8bSJeremy L Thompson int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
4762b730f8bSJeremy L Thompson                               CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
4775fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
4785fe0d4faSjeremylt     Ceed delegate;
4796574a04fSJeremy L Thompson 
4802b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
48177d1c127SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
4822b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
483e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
4845fe0d4faSjeremylt   }
4855fe0d4faSjeremylt 
4866574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
4876574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
4886574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
489e022e1f8SJeremy L Thompson 
4902b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
491db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
492d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
493d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
494d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
495d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
496d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
497d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
498d1d35e2fSjeremylt   (*rstr)->num_blk     = num_elem;
499d1d35e2fSjeremylt   (*rstr)->blk_size    = 1;
500fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_DEFAULT;
501fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, NULL, *rstr));
502e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
503d7b241e6Sjeremylt }
504d7b241e6Sjeremylt 
505d7b241e6Sjeremylt /**
50677d1c127SSebastian Grimberg   @brief Create a CeedElemRestriction with orientation signs
507fc0567d9Srezgarshakeri 
508ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
509ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array
510ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
511ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
512fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
513fcbe8c06SSebastian Grimberg                             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.
514fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
515fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
516ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
517ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
518fcbe8c06SSebastian Grimberg   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
519fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
520fcbe8c06SSebastian Grimberg 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
52177d1c127SSebastian Grimberg   @param[in]  orients     Array of shape [@a num_elem, @a elem_size] with bool false for positively oriented and true to flip the orientation.
522ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
523fc0567d9Srezgarshakeri 
524fc0567d9Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
525fc0567d9Srezgarshakeri 
526fc0567d9Srezgarshakeri   @ref User
527fc0567d9Srezgarshakeri **/
5282b730f8bSJeremy L Thompson int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
52977d1c127SSebastian Grimberg                                       CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orients,
530fc0567d9Srezgarshakeri                                       CeedElemRestriction *rstr) {
531fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreate) {
532fc0567d9Srezgarshakeri     Ceed delegate;
5336574a04fSJeremy L Thompson 
5342b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
535fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
5362b730f8bSJeremy L Thompson     CeedCall(
53777d1c127SSebastian Grimberg         CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, orients, rstr));
538fc0567d9Srezgarshakeri     return CEED_ERROR_SUCCESS;
539fc0567d9Srezgarshakeri   }
540fc0567d9Srezgarshakeri 
5416574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
5426574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
5436574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
544e022e1f8SJeremy L Thompson 
5452b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
546db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
547fc0567d9Srezgarshakeri   (*rstr)->ref_count   = 1;
548fc0567d9Srezgarshakeri   (*rstr)->num_elem    = num_elem;
549fc0567d9Srezgarshakeri   (*rstr)->elem_size   = elem_size;
550fc0567d9Srezgarshakeri   (*rstr)->num_comp    = num_comp;
551fc0567d9Srezgarshakeri   (*rstr)->comp_stride = comp_stride;
552fc0567d9Srezgarshakeri   (*rstr)->l_size      = l_size;
553fc0567d9Srezgarshakeri   (*rstr)->num_blk     = num_elem;
554fc0567d9Srezgarshakeri   (*rstr)->blk_size    = 1;
555fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_ORIENTED;
556fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, orients, NULL, *rstr));
55777d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
55877d1c127SSebastian Grimberg }
55977d1c127SSebastian Grimberg 
56077d1c127SSebastian Grimberg /**
56177d1c127SSebastian Grimberg   @brief Create a CeedElemRestriction with a general tridiagonal transformation matrix for curl-conforming elements
56277d1c127SSebastian Grimberg 
56377d1c127SSebastian Grimberg   @param[in]  ceed         Ceed object where the CeedElemRestriction will be created
56477d1c127SSebastian Grimberg   @param[in]  num_elem     Number of elements described in the @a offsets array
56577d1c127SSebastian Grimberg   @param[in]  elem_size    Size (number of "nodes") per element
56677d1c127SSebastian Grimberg   @param[in]  num_comp     Number of field components per interpolation node (1 for scalar fields)
567fcbe8c06SSebastian Grimberg   @param[in]  comp_stride  Stride between components for the same L-vector "node".
568fcbe8c06SSebastian Grimberg                              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.
569fcbe8c06SSebastian Grimberg   @param[in]  l_size       The size of the L-vector.
570fcbe8c06SSebastian Grimberg                              This vector may be larger than the elements and fields given by this restriction.
57177d1c127SSebastian Grimberg   @param[in]  mem_type     Memory type of the @a offsets array, see CeedMemType
57277d1c127SSebastian Grimberg   @param[in]  copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
573fcbe8c06SSebastian Grimberg   @param[in]  offsets      Array of shape [@a num_elem, @a elem_size].
574fcbe8c06SSebastian Grimberg                              Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i,
575fcbe8c06SSebastian Grimberg where 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
57677d1c127SSebastian Grimberg   @param[in]  curl_orients Array of shape [@a num_elem, @a 3 * elem_size] representing a row-major tridiagonal matrix (curl_orients[0] =
57777d1c127SSebastian Grimberg curl_orients[(i + 1) * 3 * elem_size - 1] = 0, where 0 <= i < @a num_elem) which is applied to the element unknowns upon restriction. This orientation
57877d1c127SSebastian Grimberg matrix allows for pairs of face degrees of freedom on elements for H(curl) spaces to be coupled in the element restriction operation, which is a way
57977d1c127SSebastian Grimberg to resolve face orientation issues for 3D meshes (https://dl.acm.org/doi/pdf/10.1145/3524456).
58077d1c127SSebastian Grimberg   @param[out] rstr         Address of the variable where the newly created CeedElemRestriction will be stored
58177d1c127SSebastian Grimberg 
58277d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
58377d1c127SSebastian Grimberg 
58477d1c127SSebastian Grimberg   @ref User
58577d1c127SSebastian Grimberg **/
58677d1c127SSebastian Grimberg int CeedElemRestrictionCreateCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
587*0c73c039SSebastian Grimberg                                           CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const CeedInt8 *curl_orients,
58877d1c127SSebastian Grimberg                                           CeedElemRestriction *rstr) {
589fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreate) {
59077d1c127SSebastian Grimberg     Ceed delegate;
59177d1c127SSebastian Grimberg 
59277d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
593fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
59477d1c127SSebastian Grimberg     CeedCall(CeedElemRestrictionCreateCurlOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
59577d1c127SSebastian Grimberg                                                    curl_orients, rstr));
59677d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
59777d1c127SSebastian Grimberg   }
59877d1c127SSebastian Grimberg 
59977d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
60077d1c127SSebastian Grimberg   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
60177d1c127SSebastian Grimberg   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
60277d1c127SSebastian Grimberg 
60377d1c127SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
604fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
60577d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
60677d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
60777d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
60877d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
60977d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
61077d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
61177d1c127SSebastian Grimberg   (*rstr)->num_blk     = num_elem;
61277d1c127SSebastian Grimberg   (*rstr)->blk_size    = 1;
613fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_CURL_ORIENTED;
614fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, curl_orients, *rstr));
615fc0567d9Srezgarshakeri   return CEED_ERROR_SUCCESS;
616fc0567d9Srezgarshakeri }
617fc0567d9Srezgarshakeri 
618fc0567d9Srezgarshakeri /**
6197509a596Sjeremylt   @brief Create a strided CeedElemRestriction
620d7b241e6Sjeremylt 
621ea61e9acSJeremy L Thompson   @param[in]  ceed      Ceed object where the CeedElemRestriction will be created
622ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
623ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
624ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation "node" (1 for scalar fields)
625fcbe8c06SSebastian Grimberg   @param[in]  l_size    The size of the L-vector.
626fcbe8c06SSebastian Grimberg                           This vector may be larger than the elements and fields given by this restriction.
627fcbe8c06SSebastian Grimberg   @param[in]  strides   Array for strides between [nodes, components, elements].
628fcbe8c06SSebastian Grimberg                           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].
629fcbe8c06SSebastian Grimberg                           @a CEED_STRIDES_BACKEND may be used with vectors created by a Ceed backend.
630ea61e9acSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created CeedElemRestriction will be stored
631d7b241e6Sjeremylt 
632b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
633dfdf5a53Sjeremylt 
6347a982d89SJeremy L. Thompson   @ref User
635b11c1e72Sjeremylt **/
6362b730f8bSJeremy L Thompson int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedSize l_size, const CeedInt strides[3],
637f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
6385fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
6395fe0d4faSjeremylt     Ceed delegate;
640b04eb3d9SSebastian Grimberg 
6412b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
642fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
6432b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, l_size, strides, rstr));
644e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6455fe0d4faSjeremylt   }
6465fe0d4faSjeremylt 
6476574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
6486574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
649e022e1f8SJeremy L Thompson 
6502b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
651db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
652d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
653d1d35e2fSjeremylt   (*rstr)->num_elem  = num_elem;
654d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
655d1d35e2fSjeremylt   (*rstr)->num_comp  = num_comp;
656d1d35e2fSjeremylt   (*rstr)->l_size    = l_size;
657d1d35e2fSjeremylt   (*rstr)->num_blk   = num_elem;
658d1d35e2fSjeremylt   (*rstr)->blk_size  = 1;
659fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type = CEED_RESTRICTION_STRIDED;
6602b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
6612b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
662fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
663e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
664d7b241e6Sjeremylt }
665d7b241e6Sjeremylt 
666d7b241e6Sjeremylt /**
667b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
668d7b241e6Sjeremylt 
669ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created.
670ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array.
671ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of unknowns) per element
672ea61e9acSJeremy L Thompson   @param[in]  blk_size    Number of elements in a block
673ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
674fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
675fcbe8c06SSebastian Grimberg                             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.
676fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
677fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
678ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
679ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
680fcbe8c06SSebastian Grimberg   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
681fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
682fcbe8c06SSebastian Grimberg  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
683fcbe8c06SSebastian Grimberg  the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
684ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
685d7b241e6Sjeremylt 
686b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
687dfdf5a53Sjeremylt 
6887a982d89SJeremy L. Thompson   @ref Backend
689b11c1e72Sjeremylt  **/
6902b730f8bSJeremy L Thompson int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedInt comp_stride,
6912b730f8bSJeremy L Thompson                                      CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets,
6924ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
693d1d35e2fSjeremylt   CeedInt *blk_offsets;
694d1d35e2fSjeremylt   CeedInt  num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
695d7b241e6Sjeremylt 
6965fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
6975fe0d4faSjeremylt     Ceed delegate;
6986574a04fSJeremy L Thompson 
6992b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
7006402da51SJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
7012b730f8bSJeremy L Thompson     CeedCall(
7022b730f8bSJeremy L Thompson         CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, blk_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
703e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
7045fe0d4faSjeremylt   }
705d7b241e6Sjeremylt 
7066574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
7076574a04fSJeremy L Thompson   CeedCheck(blk_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
7086574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
7096574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
710e022e1f8SJeremy L Thompson 
7112b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(num_blk * blk_size * elem_size, &blk_offsets));
7122b730f8bSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size, elem_size));
713d7b241e6Sjeremylt 
714db002c03SJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
715db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
716d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
717d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
718d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
719d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
720d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
721d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
722d1d35e2fSjeremylt   (*rstr)->num_blk     = num_blk;
723d1d35e2fSjeremylt   (*rstr)->blk_size    = blk_size;
724fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_DEFAULT;
725fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)blk_offsets, NULL, NULL, *rstr));
726d1d35e2fSjeremylt   if (copy_mode == CEED_OWN_POINTER) {
7272b730f8bSJeremy L Thompson     CeedCall(CeedFree(&offsets));
7281d102b48SJeremy L Thompson   }
729e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
730d7b241e6Sjeremylt }
731d7b241e6Sjeremylt 
732b11c1e72Sjeremylt /**
73377d1c127SSebastian Grimberg   @brief Create a blocked oriented CeedElemRestriction, typically only called by backends
73477d1c127SSebastian Grimberg 
73577d1c127SSebastian Grimberg   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created.
73677d1c127SSebastian Grimberg   @param[in]  num_elem    Number of elements described in the @a offsets array.
73777d1c127SSebastian Grimberg   @param[in]  elem_size   Size (number of unknowns) per element
73877d1c127SSebastian Grimberg   @param[in]  blk_size    Number of elements in a block
73977d1c127SSebastian Grimberg   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
740fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
741fcbe8c06SSebastian Grimberg                             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.
742fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
743fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
74477d1c127SSebastian Grimberg   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
74577d1c127SSebastian Grimberg   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
746fcbe8c06SSebastian Grimberg   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
747fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
748fcbe8c06SSebastian Grimberg  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
749fcbe8c06SSebastian Grimberg  the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
750fcbe8c06SSebastian Grimberg   @param[in]  orients     Array of shape [@a num_elem, @a elem_size] with bool false for positively oriented and true to flip the orientation.
751fcbe8c06SSebastian Grimberg                             Will also be permuted and padded similarly to @a offsets.
75277d1c127SSebastian Grimberg   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
75377d1c127SSebastian Grimberg 
75477d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
75577d1c127SSebastian Grimberg 
75677d1c127SSebastian Grimberg   @ref Backend
75777d1c127SSebastian Grimberg  **/
75877d1c127SSebastian Grimberg int CeedElemRestrictionCreateBlockedOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedInt comp_stride,
75977d1c127SSebastian Grimberg                                              CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets,
76077d1c127SSebastian Grimberg                                              const bool *orients, CeedElemRestriction *rstr) {
76177d1c127SSebastian Grimberg   CeedInt *blk_offsets;
76277d1c127SSebastian Grimberg   bool    *blk_orients;
76377d1c127SSebastian Grimberg   CeedInt  num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
76477d1c127SSebastian Grimberg 
765fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreateBlocked) {
76677d1c127SSebastian Grimberg     Ceed delegate;
76777d1c127SSebastian Grimberg 
76877d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
769fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
77077d1c127SSebastian Grimberg     CeedCall(CeedElemRestrictionCreateBlockedOriented(delegate, num_elem, elem_size, blk_size, num_comp, comp_stride, l_size, mem_type, copy_mode,
77177d1c127SSebastian Grimberg                                                       offsets, orients, rstr));
77277d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
77377d1c127SSebastian Grimberg   }
77477d1c127SSebastian Grimberg 
77577d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
77677d1c127SSebastian Grimberg   CeedCheck(blk_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
77777d1c127SSebastian Grimberg   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
77877d1c127SSebastian Grimberg   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
77977d1c127SSebastian Grimberg 
78077d1c127SSebastian Grimberg   CeedCall(CeedCalloc(num_blk * blk_size * elem_size, &blk_offsets));
78177d1c127SSebastian Grimberg   CeedCall(CeedCalloc(num_blk * blk_size * elem_size, &blk_orients));
78277d1c127SSebastian Grimberg   CeedCall(CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size, elem_size));
783*0c73c039SSebastian Grimberg   CeedCall(CeedPermutePadOrients(orients, blk_orients, num_blk, num_elem, blk_size, elem_size));
78477d1c127SSebastian Grimberg 
785fcbe8c06SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
786fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
78777d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
78877d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
78977d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
79077d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
79177d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
79277d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
79377d1c127SSebastian Grimberg   (*rstr)->num_blk     = num_blk;
79477d1c127SSebastian Grimberg   (*rstr)->blk_size    = blk_size;
795fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_ORIENTED;
796fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)blk_offsets, (const bool *)blk_orients, NULL, *rstr));
79777d1c127SSebastian Grimberg   if (copy_mode == CEED_OWN_POINTER) {
79877d1c127SSebastian Grimberg     CeedCall(CeedFree(&offsets));
79977d1c127SSebastian Grimberg   }
80077d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
80177d1c127SSebastian Grimberg }
80277d1c127SSebastian Grimberg 
80377d1c127SSebastian Grimberg /**
80477d1c127SSebastian Grimberg   @brief Create a blocked curl-oriented CeedElemRestriction, typically only called by backends
80577d1c127SSebastian Grimberg 
80677d1c127SSebastian Grimberg   @param[in]  ceed         Ceed object where the CeedElemRestriction will be created.
80777d1c127SSebastian Grimberg   @param[in]  num_elem     Number of elements described in the @a offsets array.
80877d1c127SSebastian Grimberg   @param[in]  elem_size    Size (number of unknowns) per element
80977d1c127SSebastian Grimberg   @param[in]  blk_size     Number of elements in a block
81077d1c127SSebastian Grimberg   @param[in]  num_comp     Number of field components per interpolation node (1 for scalar fields)
811fcbe8c06SSebastian Grimberg   @param[in]  comp_stride  Stride between components for the same L-vector "node".
812fcbe8c06SSebastian Grimberg                              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.
813fcbe8c06SSebastian Grimberg   @param[in]  l_size       The size of the L-vector.
814fcbe8c06SSebastian Grimberg                              This vector may be larger than the elements and fields given by this restriction.
81577d1c127SSebastian Grimberg   @param[in]  mem_type     Memory type of the @a offsets array, see CeedMemType
81677d1c127SSebastian Grimberg   @param[in]  copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
817fcbe8c06SSebastian Grimberg   @param[in]  offsets      Array of shape [@a num_elem, @a elem_size].
818fcbe8c06SSebastian Grimberg                              Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i,
819fcbe8c06SSebastian Grimberg where 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
820fcbe8c06SSebastian Grimberg for the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
82177d1c127SSebastian Grimberg   @param[in]  curl_orients Array of shape [@a num_elem, @a 3 * elem_size] representing a row-major tridiagonal matrix (curl_orients[0] =
822fcbe8c06SSebastian Grimberg curl_orients[(i + 1) * 3 * elem_size - 1] = 0, where 0 <= i < @a num_elem) which is applied to the element unknowns upon restriction.
823fcbe8c06SSebastian Grimberg                              This orientation matrix allows for pairs of face degrees of freedom on elements for H(curl) spaces to be coupled in the
824fcbe8c06SSebastian Grimberg element restriction operation, which is a way to resolve face orientation issues for 3D meshes (https://dl.acm.org/doi/pdf/10.1145/3524456). Will also
825fcbe8c06SSebastian Grimberg be permuted and padded similarly to @a offsets.
82677d1c127SSebastian Grimberg   @param[out] rstr         Address of the variable where the newly created CeedElemRestriction will be stored
82777d1c127SSebastian Grimberg 
82877d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
82977d1c127SSebastian Grimberg 
83077d1c127SSebastian Grimberg   @ref Backend
83177d1c127SSebastian Grimberg  **/
83277d1c127SSebastian Grimberg int CeedElemRestrictionCreateBlockedCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp,
83377d1c127SSebastian Grimberg                                                  CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode,
834*0c73c039SSebastian Grimberg                                                  const CeedInt *offsets, const CeedInt8 *curl_orients, CeedElemRestriction *rstr) {
83577d1c127SSebastian Grimberg   CeedInt  *blk_offsets;
836*0c73c039SSebastian Grimberg   CeedInt8 *blk_curl_orients;
83777d1c127SSebastian Grimberg   CeedInt   num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
83877d1c127SSebastian Grimberg 
839fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreateBlocked) {
84077d1c127SSebastian Grimberg     Ceed delegate;
84177d1c127SSebastian Grimberg 
84277d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
843fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
84477d1c127SSebastian Grimberg     CeedCall(CeedElemRestrictionCreateBlockedCurlOriented(delegate, num_elem, elem_size, blk_size, num_comp, comp_stride, l_size, mem_type, copy_mode,
84577d1c127SSebastian Grimberg                                                           offsets, curl_orients, rstr));
84677d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
84777d1c127SSebastian Grimberg   }
84877d1c127SSebastian Grimberg 
84977d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
85077d1c127SSebastian Grimberg   CeedCheck(blk_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
85177d1c127SSebastian Grimberg   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
85277d1c127SSebastian Grimberg   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
85377d1c127SSebastian Grimberg 
85477d1c127SSebastian Grimberg   CeedCall(CeedCalloc(num_blk * blk_size * elem_size, &blk_offsets));
85577d1c127SSebastian Grimberg   CeedCall(CeedCalloc(num_blk * blk_size * 3 * elem_size, &blk_curl_orients));
85677d1c127SSebastian Grimberg   CeedCall(CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size, elem_size));
857*0c73c039SSebastian Grimberg   CeedCall(CeedPermutePadCurlOrients(curl_orients, blk_curl_orients, num_blk, num_elem, blk_size, 3 * elem_size));
85877d1c127SSebastian Grimberg 
859fcbe8c06SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
860fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
86177d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
86277d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
86377d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
86477d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
86577d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
86677d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
86777d1c127SSebastian Grimberg   (*rstr)->num_blk     = num_blk;
86877d1c127SSebastian Grimberg   (*rstr)->blk_size    = blk_size;
869fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_CURL_ORIENTED;
870*0c73c039SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)blk_offsets, NULL, (const CeedInt8 *)blk_curl_orients,
871fcbe8c06SSebastian Grimberg                                               *rstr));
87277d1c127SSebastian Grimberg   if (copy_mode == CEED_OWN_POINTER) {
87377d1c127SSebastian Grimberg     CeedCall(CeedFree(&offsets));
87477d1c127SSebastian Grimberg   }
87577d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
87677d1c127SSebastian Grimberg }
87777d1c127SSebastian Grimberg 
87877d1c127SSebastian Grimberg /**
87977d1c127SSebastian Grimberg   @brief Create a blocked strided CeedElemRestriction, typically only called by backends
8807509a596Sjeremylt 
881ea61e9acSJeremy L Thompson   @param[in]  ceed      Ceed object where the CeedElemRestriction will be created
882ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
883ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
884ea61e9acSJeremy L Thompson   @param[in]  blk_size  Number of elements in a block
885ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation node (1 for scalar fields)
886fcbe8c06SSebastian Grimberg   @param[in]  l_size    The size of the L-vector.
887fcbe8c06SSebastian Grimberg                           This vector may be larger than the elements and fields given by this restriction.
888fcbe8c06SSebastian Grimberg   @param[in]  strides   Array for strides between [nodes, components, elements].
889fcbe8c06SSebastian Grimberg                           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].
890fcbe8c06SSebastian Grimberg                           @a CEED_STRIDES_BACKEND may be used with vectors created by a Ceed backend.
891ea61e9acSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created CeedElemRestriction will be stored
8927509a596Sjeremylt 
8937509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
8947509a596Sjeremylt 
8957a982d89SJeremy L. Thompson   @ref User
8967509a596Sjeremylt **/
8972b730f8bSJeremy L Thompson int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedSize l_size,
8988621c6c6SJeremy L Thompson                                             const CeedInt strides[3], CeedElemRestriction *rstr) {
899d1d35e2fSjeremylt   CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
9007509a596Sjeremylt 
9017509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
9027509a596Sjeremylt     Ceed delegate;
9036574a04fSJeremy L Thompson 
9042b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
905fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
9062b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, blk_size, num_comp, l_size, strides, rstr));
907e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
9087509a596Sjeremylt   }
9097509a596Sjeremylt 
9106574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
9116574a04fSJeremy L Thompson   CeedCheck(blk_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
9126574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
913e022e1f8SJeremy L Thompson 
9142b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
915db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
916d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
917d1d35e2fSjeremylt   (*rstr)->num_elem  = num_elem;
918d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
919d1d35e2fSjeremylt   (*rstr)->num_comp  = num_comp;
920d1d35e2fSjeremylt   (*rstr)->l_size    = l_size;
921d1d35e2fSjeremylt   (*rstr)->num_blk   = num_blk;
922d1d35e2fSjeremylt   (*rstr)->blk_size  = blk_size;
923fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type = CEED_RESTRICTION_STRIDED;
9242b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
9252b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
926fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
927e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
9287509a596Sjeremylt }
9297509a596Sjeremylt 
9307509a596Sjeremylt /**
931c17ec2beSJeremy L Thompson   @brief Copy the pointer to a CeedElemRestriction and set `CeedElemRestrictionApply()` implementation to `CeedElemRestrictionApplyUnsigned()`.
932c17ec2beSJeremy L Thompson 
933c17ec2beSJeremy L Thompson   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
934c17ec2beSJeremy L Thompson 
935c17ec2beSJeremy L Thompson   @param[in]     rstr          CeedElemRestriction to create unsigned reference to
936c17ec2beSJeremy L Thompson   @param[in,out] rstr_unsigned Variable to store unsigned CeedElemRestriction
937c17ec2beSJeremy L Thompson 
938c17ec2beSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
939c17ec2beSJeremy L Thompson 
940c17ec2beSJeremy L Thompson   @ref User
941c17ec2beSJeremy L Thompson **/
942c17ec2beSJeremy L Thompson int CeedElemRestrictionCreateUnsignedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unsigned) {
943c17ec2beSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr_unsigned));
944c17ec2beSJeremy L Thompson 
945c17ec2beSJeremy L Thompson   // Copy old rstr
946c17ec2beSJeremy L Thompson   memcpy(*rstr_unsigned, rstr, sizeof(struct CeedElemRestriction_private));
947c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ceed = NULL;
948c17ec2beSJeremy L Thompson   CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unsigned)->ceed));
949c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ref_count = 1;
950c17ec2beSJeremy L Thompson   (*rstr_unsigned)->strides   = NULL;
951c17ec2beSJeremy L Thompson   if (rstr->strides) {
952c17ec2beSJeremy L Thompson     CeedCall(CeedMalloc(3, &(*rstr_unsigned)->strides));
953c17ec2beSJeremy L Thompson     for (CeedInt i = 0; i < 3; i++) (*rstr_unsigned)->strides[i] = rstr->strides[i];
954c17ec2beSJeremy L Thompson   }
955c17ec2beSJeremy L Thompson   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unsigned)->rstr_signed));
956c17ec2beSJeremy L Thompson 
957c17ec2beSJeremy L Thompson   // Override Apply
958c17ec2beSJeremy L Thompson   (*rstr_unsigned)->Apply = rstr->ApplyUnsigned;
959c17ec2beSJeremy L Thompson 
960c17ec2beSJeremy L Thompson   return CEED_ERROR_SUCCESS;
961c17ec2beSJeremy L Thompson }
962c17ec2beSJeremy L Thompson 
963c17ec2beSJeremy L Thompson /**
964ea61e9acSJeremy L Thompson   @brief Copy the pointer to a CeedElemRestriction.
9659fd66db6SSebastian Grimberg 
966ea61e9acSJeremy L Thompson   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
9679560d06aSjeremylt 
9689fd66db6SSebastian 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.
9699fd66db6SSebastian Grimberg         This CeedElemRestriction will be destroyed if `rstr_copy` is the only reference to this CeedElemRestriction.
970ea61e9acSJeremy L Thompson 
971ea61e9acSJeremy L Thompson   @param[in]     rstr      CeedElemRestriction to copy reference to
972ea61e9acSJeremy L Thompson   @param[in,out] rstr_copy Variable to store copied reference
9739560d06aSjeremylt 
9749560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
9759560d06aSjeremylt 
9769560d06aSjeremylt   @ref User
9779560d06aSjeremylt **/
9782b730f8bSJeremy L Thompson int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_copy) {
979393ac2cdSJeremy L Thompson   if (rstr != CEED_ELEMRESTRICTION_NONE) CeedCall(CeedElemRestrictionReference(rstr));
9802b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionDestroy(rstr_copy));
9819560d06aSjeremylt   *rstr_copy = rstr;
9829560d06aSjeremylt   return CEED_ERROR_SUCCESS;
9839560d06aSjeremylt }
9849560d06aSjeremylt 
9859560d06aSjeremylt /**
986b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
987b11c1e72Sjeremylt 
988ea61e9acSJeremy L Thompson   @param[in]  rstr  CeedElemRestriction
989ea61e9acSJeremy L Thompson   @param[out] l_vec The address of the L-vector to be created, or NULL
990ea61e9acSJeremy L Thompson   @param[out] e_vec The address of the E-vector to be created, or NULL
991b11c1e72Sjeremylt 
992b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
993dfdf5a53Sjeremylt 
9947a982d89SJeremy L. Thompson   @ref User
995b11c1e72Sjeremylt **/
9962b730f8bSJeremy L Thompson int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, CeedVector *e_vec) {
997d2643443SJeremy L Thompson   CeedSize e_size, l_size;
998d1d35e2fSjeremylt   l_size = rstr->l_size;
999d1d35e2fSjeremylt   e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
10002b730f8bSJeremy L Thompson   if (l_vec) CeedCall(CeedVectorCreate(rstr->ceed, l_size, l_vec));
10012b730f8bSJeremy L Thompson   if (e_vec) CeedCall(CeedVectorCreate(rstr->ceed, e_size, e_vec));
1002e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1003d7b241e6Sjeremylt }
1004d7b241e6Sjeremylt 
1005d7b241e6Sjeremylt /**
1006d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
1007d7b241e6Sjeremylt 
1008ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
1009ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1010ea61e9acSJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
1011fcbe8c06SSebastian Grimberg   @param[out] ru      Output vector (of shape [@a num_elem * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
1012fcbe8c06SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
1013ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
1014b11c1e72Sjeremylt 
1015b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1016dfdf5a53Sjeremylt 
10177a982d89SJeremy L. Thompson   @ref User
1018b11c1e72Sjeremylt **/
10192b730f8bSJeremy L Thompson int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
1020d7b241e6Sjeremylt   CeedInt m, n;
1021d7b241e6Sjeremylt 
1022d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
1023d1d35e2fSjeremylt     m = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
1024d1d35e2fSjeremylt     n = rstr->l_size;
1025d7b241e6Sjeremylt   } else {
1026d1d35e2fSjeremylt     m = rstr->l_size;
1027d1d35e2fSjeremylt     n = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
1028d7b241e6Sjeremylt   }
10296574a04fSJeremy L Thompson   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
10306574a04fSJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
10316574a04fSJeremy L Thompson   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
10326574a04fSJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
10332b730f8bSJeremy L Thompson   if (rstr->num_elem > 0) CeedCall(rstr->Apply(rstr, t_mode, u, ru, request));
1034e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1035d7b241e6Sjeremylt }
1036d7b241e6Sjeremylt 
1037d7b241e6Sjeremylt /**
1038d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
1039be9261b7Sjeremylt 
1040ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
1041ea61e9acSJeremy 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
1042ea61e9acSJeremy L Thompson : 4*blk_size]
1043ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1044ea61e9acSJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
1045fcbe8c06SSebastian Grimberg   @param[out] ru      Output vector (of shape [@a blk_size * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
1046fcbe8c06SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
1047ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
1048be9261b7Sjeremylt 
1049be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
1050be9261b7Sjeremylt 
10517a982d89SJeremy L. Thompson   @ref Backend
1052be9261b7Sjeremylt **/
10532b730f8bSJeremy L Thompson int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
10542b730f8bSJeremy L Thompson                                   CeedRequest *request) {
1055be9261b7Sjeremylt   CeedInt m, n;
1056be9261b7Sjeremylt 
10576402da51SJeremy L Thompson   CeedCheck(rstr->ApplyBlock, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionApplyBlock");
10586402da51SJeremy L Thompson 
1059d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
1060d1d35e2fSjeremylt     m = rstr->blk_size * rstr->elem_size * rstr->num_comp;
1061d1d35e2fSjeremylt     n = rstr->l_size;
1062be9261b7Sjeremylt   } else {
1063d1d35e2fSjeremylt     m = rstr->l_size;
1064d1d35e2fSjeremylt     n = rstr->blk_size * rstr->elem_size * rstr->num_comp;
1065be9261b7Sjeremylt   }
10666574a04fSJeremy L Thompson   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
10676574a04fSJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
10686574a04fSJeremy L Thompson   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
10696574a04fSJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
10706574a04fSJeremy L Thompson   CeedCheck(rstr->blk_size * block <= rstr->num_elem, rstr->ceed, CEED_ERROR_DIMENSION,
10716574a04fSJeremy L Thompson             "Cannot retrieve block %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", block, rstr->blk_size * block,
10726574a04fSJeremy L Thompson             rstr->num_elem);
10732b730f8bSJeremy L Thompson   CeedCall(rstr->ApplyBlock(rstr, block, t_mode, u, ru, request));
1074e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1075be9261b7Sjeremylt }
1076be9261b7Sjeremylt 
1077be9261b7Sjeremylt /**
1078b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedElemRestriction
1079b7c9bbdaSJeremy L Thompson 
1080ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
1081b7c9bbdaSJeremy L Thompson   @param[out] ceed Variable to store Ceed
1082b7c9bbdaSJeremy L Thompson 
1083b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1084b7c9bbdaSJeremy L Thompson 
1085b7c9bbdaSJeremy L Thompson   @ref Advanced
1086b7c9bbdaSJeremy L Thompson **/
1087b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
1088b7c9bbdaSJeremy L Thompson   *ceed = rstr->ceed;
1089b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1090b7c9bbdaSJeremy L Thompson }
1091b7c9bbdaSJeremy L Thompson 
1092b7c9bbdaSJeremy L Thompson /**
1093d979a051Sjeremylt   @brief Get the L-vector component stride
1094a681ae63Sjeremylt 
1095ea61e9acSJeremy L Thompson   @param[in]  rstr        CeedElemRestriction
1096d1d35e2fSjeremylt   @param[out] comp_stride Variable to store component stride
1097a681ae63Sjeremylt 
1098a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1099a681ae63Sjeremylt 
1100b7c9bbdaSJeremy L Thompson   @ref Advanced
1101a681ae63Sjeremylt **/
11022b730f8bSJeremy L Thompson int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, CeedInt *comp_stride) {
1103d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
1104e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1105a681ae63Sjeremylt }
1106a681ae63Sjeremylt 
1107a681ae63Sjeremylt /**
1108a681ae63Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
1109a681ae63Sjeremylt 
1110ea61e9acSJeremy L Thompson   @param[in] rstr      CeedElemRestriction
1111d1d35e2fSjeremylt   @param[out] num_elem Variable to store number of elements
1112a681ae63Sjeremylt 
1113a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1114a681ae63Sjeremylt 
1115b7c9bbdaSJeremy L Thompson   @ref Advanced
1116a681ae63Sjeremylt **/
11172b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, CeedInt *num_elem) {
1118d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
1119e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1120a681ae63Sjeremylt }
1121a681ae63Sjeremylt 
1122a681ae63Sjeremylt /**
1123a681ae63Sjeremylt   @brief Get the size of elements in the CeedElemRestriction
1124a681ae63Sjeremylt 
1125ea61e9acSJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
1126d1d35e2fSjeremylt   @param[out] elem_size Variable to store size of elements
1127a681ae63Sjeremylt 
1128a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1129a681ae63Sjeremylt 
1130b7c9bbdaSJeremy L Thompson   @ref Advanced
1131a681ae63Sjeremylt **/
11322b730f8bSJeremy L Thompson int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, CeedInt *elem_size) {
1133d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
1134e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1135a681ae63Sjeremylt }
1136a681ae63Sjeremylt 
1137a681ae63Sjeremylt /**
1138d979a051Sjeremylt   @brief Get the size of the l-vector for a CeedElemRestriction
1139a681ae63Sjeremylt 
1140ea61e9acSJeremy L Thompson   @param[in]  rstr   CeedElemRestriction
1141d1d35e2fSjeremylt   @param[out] l_size Variable to store number of nodes
1142a681ae63Sjeremylt 
1143a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1144a681ae63Sjeremylt 
1145b7c9bbdaSJeremy L Thompson   @ref Advanced
1146a681ae63Sjeremylt **/
11472b730f8bSJeremy L Thompson int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, CeedSize *l_size) {
1148d1d35e2fSjeremylt   *l_size = rstr->l_size;
1149e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1150a681ae63Sjeremylt }
1151a681ae63Sjeremylt 
1152a681ae63Sjeremylt /**
1153ea61e9acSJeremy L Thompson   @brief Get the number of components in the elements of a CeedElemRestriction
1154a681ae63Sjeremylt 
1155ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction
1156d1d35e2fSjeremylt   @param[out] num_comp Variable to store number of components
1157a681ae63Sjeremylt 
1158a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1159a681ae63Sjeremylt 
1160b7c9bbdaSJeremy L Thompson   @ref Advanced
1161a681ae63Sjeremylt **/
11622b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, CeedInt *num_comp) {
1163d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
1164e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1165a681ae63Sjeremylt }
1166a681ae63Sjeremylt 
1167a681ae63Sjeremylt /**
1168a681ae63Sjeremylt   @brief Get the number of blocks in a CeedElemRestriction
1169a681ae63Sjeremylt 
1170ea61e9acSJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
1171d1d35e2fSjeremylt   @param[out] num_block Variable to store number of blocks
1172a681ae63Sjeremylt 
1173a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1174a681ae63Sjeremylt 
1175b7c9bbdaSJeremy L Thompson   @ref Advanced
1176a681ae63Sjeremylt **/
11772b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, CeedInt *num_block) {
1178d1d35e2fSjeremylt   *num_block = rstr->num_blk;
1179e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1180a681ae63Sjeremylt }
1181a681ae63Sjeremylt 
1182a681ae63Sjeremylt /**
1183a681ae63Sjeremylt   @brief Get the size of blocks in the CeedElemRestriction
1184a681ae63Sjeremylt 
1185ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction
1186d1d35e2fSjeremylt   @param[out] blk_size Variable to store size of blocks
1187a681ae63Sjeremylt 
1188a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1189a681ae63Sjeremylt 
1190b7c9bbdaSJeremy L Thompson   @ref Advanced
1191a681ae63Sjeremylt **/
11922b730f8bSJeremy L Thompson int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, CeedInt *blk_size) {
1193d1d35e2fSjeremylt   *blk_size = rstr->blk_size;
1194e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1195a681ae63Sjeremylt }
1196a681ae63Sjeremylt 
1197a681ae63Sjeremylt /**
1198d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
11991469ee4dSjeremylt 
1200ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
1201d1d35e2fSjeremylt   @param[out] mult Vector to store multiplicity (of size l_size)
12021469ee4dSjeremylt 
12031469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
12041469ee4dSjeremylt 
12057a982d89SJeremy L. Thompson   @ref User
12061469ee4dSjeremylt **/
12072b730f8bSJeremy L Thompson int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, CeedVector mult) {
1208d1d35e2fSjeremylt   CeedVector e_vec;
12091469ee4dSjeremylt 
121025509ebbSRezgar Shakeri   // Create e_vec to hold intermediate computation in E^T (E 1)
12112b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionCreateVector(rstr, NULL, &e_vec));
12121469ee4dSjeremylt 
121325509ebbSRezgar Shakeri   // Compute e_vec = E * 1
12142b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 1.0));
12152b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, CEED_REQUEST_IMMEDIATE));
121625509ebbSRezgar Shakeri   // Compute multiplicity, mult = E^T * e_vec = E^T (E 1)
12172b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 0.0));
12182b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, CEED_REQUEST_IMMEDIATE));
12191469ee4dSjeremylt   // Cleanup
12202b730f8bSJeremy L Thompson   CeedCall(CeedVectorDestroy(&e_vec));
1221e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
12221469ee4dSjeremylt }
12231469ee4dSjeremylt 
12241469ee4dSjeremylt /**
1225f02ca4a2SJed Brown   @brief View a CeedElemRestriction
1226f02ca4a2SJed Brown 
1227f02ca4a2SJed Brown   @param[in] rstr   CeedElemRestriction to view
1228f02ca4a2SJed Brown   @param[in] stream Stream to write; typically stdout/stderr or a file
1229f02ca4a2SJed Brown 
1230f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
1231f02ca4a2SJed Brown 
12327a982d89SJeremy L. Thompson   @ref User
1233f02ca4a2SJed Brown **/
1234f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
12357509a596Sjeremylt   char stridesstr[500];
12362b730f8bSJeremy L Thompson   if (rstr->strides) {
12372b730f8bSJeremy L Thompson     sprintf(stridesstr, "[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "]", rstr->strides[0], rstr->strides[1], rstr->strides[2]);
12382b730f8bSJeremy L Thompson   } else {
1239990fdeb6SJeremy L Thompson     sprintf(stridesstr, "%" CeedInt_FMT, rstr->comp_stride);
12402b730f8bSJeremy L Thompson   }
12417509a596Sjeremylt 
12422b730f8bSJeremy L Thompson   fprintf(stream, "%sCeedElemRestriction from (%td, %" CeedInt_FMT ") to %" CeedInt_FMT " elements with %" CeedInt_FMT " nodes each and %s %s\n",
12432b730f8bSJeremy L Thompson           rstr->blk_size > 1 ? "Blocked " : "", rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
1244d979a051Sjeremylt           rstr->strides ? "strides" : "component stride", stridesstr);
1245e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1246f02ca4a2SJed Brown }
1247f02ca4a2SJed Brown 
1248f02ca4a2SJed Brown /**
1249b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
1250b11c1e72Sjeremylt 
1251ea61e9acSJeremy L Thompson   @param[in,out] rstr CeedElemRestriction to destroy
1252b11c1e72Sjeremylt 
1253b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1254dfdf5a53Sjeremylt 
12557a982d89SJeremy L. Thompson   @ref User
1256b11c1e72Sjeremylt **/
12574ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
1258393ac2cdSJeremy L Thompson   if (!*rstr || *rstr == CEED_ELEMRESTRICTION_NONE || --(*rstr)->ref_count > 0) {
1259ad6481ceSJeremy L Thompson     *rstr = NULL;
1260ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
1261ad6481ceSJeremy L Thompson   }
12626574a04fSJeremy L Thompson   CeedCheck((*rstr)->num_readers == 0, (*rstr)->ceed, CEED_ERROR_ACCESS,
12636574a04fSJeremy L Thompson             "Cannot destroy CeedElemRestriction, a process has read access to the offset data");
1264c17ec2beSJeremy L Thompson 
1265c17ec2beSJeremy L Thompson   // Only destroy backend data once between rstr and unsigned copy
1266c17ec2beSJeremy L Thompson   if ((*rstr)->rstr_signed) CeedCall(CeedElemRestrictionDestroy(&(*rstr)->rstr_signed));
1267c17ec2beSJeremy L Thompson   else if ((*rstr)->Destroy) CeedCall((*rstr)->Destroy(*rstr));
1268c17ec2beSJeremy L Thompson 
12692b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*rstr)->strides));
12702b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*rstr)->ceed));
12712b730f8bSJeremy L Thompson   CeedCall(CeedFree(rstr));
1272e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1273d7b241e6Sjeremylt }
1274d7b241e6Sjeremylt 
1275d7b241e6Sjeremylt /// @}
1276