xref: /libCEED/interface/ceed-elemrestriction.c (revision fcbe8c069ccd22d836386af4823e4c7d84ee0a69)
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 
27*fcbe8c06SSebastian Grimberg   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
28*fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
29*fcbe8c06SSebastian Grimberg 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
30ea61e9acSJeremy L Thompson   @param[out] blk_offsets Array of permuted and padded offsets of shape [@a num_blk, @a elem_size, @a blk_size].
31ea61e9acSJeremy L Thompson   @param[in]  num_blk     Number of blocks
32ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements
33ea61e9acSJeremy L Thompson   @param[in]  blk_size    Number of elements in a block
34ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size of each element
357a982d89SJeremy L. Thompson 
367a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
377a982d89SJeremy L. Thompson 
387a982d89SJeremy L. Thompson   @ref Utility
397a982d89SJeremy L. Thompson **/
402b730f8bSJeremy L Thompson int CeedPermutePadOffsets(const CeedInt *offsets, CeedInt *blk_offsets, CeedInt num_blk, CeedInt num_elem, CeedInt blk_size, CeedInt elem_size) {
412b730f8bSJeremy L Thompson   for (CeedInt e = 0; e < num_blk * blk_size; e += blk_size) {
422b730f8bSJeremy L Thompson     for (CeedInt j = 0; j < blk_size; j++) {
432b730f8bSJeremy L Thompson       for (CeedInt k = 0; k < elem_size; k++) {
442b730f8bSJeremy L Thompson         blk_offsets[e * elem_size + k * blk_size + j] = offsets[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
452b730f8bSJeremy L Thompson       }
462b730f8bSJeremy L Thompson     }
472b730f8bSJeremy L Thompson   }
48e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
497a982d89SJeremy L. Thompson }
507a982d89SJeremy L. Thompson 
5177d1c127SSebastian Grimberg /**
5277d1c127SSebastian Grimberg   @brief Permute and pad orientations for a blocked restriction
5377d1c127SSebastian Grimberg 
54*fcbe8c06SSebastian Grimberg   @param[in]  orients     Array of shape [@a num_elem, @a elem_size].
55*fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the orientations (into the input CeedVector) for
5677d1c127SSebastian Grimberg the unknowns corresponding to element i, where 0 <= i < @a num_elem.
5777d1c127SSebastian Grimberg   @param[out] blk_orients Array of permuted and padded orientations of shape [@a num_blk, @a elem_size, @a blk_size].
5877d1c127SSebastian Grimberg   @param[in]  num_blk     Number of blocks
5977d1c127SSebastian Grimberg   @param[in]  num_elem    Number of elements
6077d1c127SSebastian Grimberg   @param[in]  blk_size    Number of elements in a block
6177d1c127SSebastian Grimberg   @param[in]  elem_size   Size of each element
6277d1c127SSebastian Grimberg 
6377d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
6477d1c127SSebastian Grimberg 
6577d1c127SSebastian Grimberg   @ref Utility
6677d1c127SSebastian Grimberg **/
6777d1c127SSebastian Grimberg int CeedPermutePadOrientations(const bool *orients, bool *blk_orients, CeedInt num_blk, CeedInt num_elem, CeedInt blk_size, CeedInt elem_size) {
6877d1c127SSebastian Grimberg   for (CeedInt e = 0; e < num_blk * blk_size; e += blk_size) {
6977d1c127SSebastian Grimberg     for (CeedInt j = 0; j < blk_size; j++) {
7077d1c127SSebastian Grimberg       for (CeedInt k = 0; k < elem_size; k++) {
7177d1c127SSebastian Grimberg         blk_orients[e * elem_size + k * blk_size + j] = orients[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
7277d1c127SSebastian Grimberg       }
7377d1c127SSebastian Grimberg     }
7477d1c127SSebastian Grimberg   }
7577d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
7677d1c127SSebastian Grimberg }
7777d1c127SSebastian Grimberg 
787a982d89SJeremy L. Thompson /// @}
797a982d89SJeremy L. Thompson 
807a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
817a982d89SJeremy L. Thompson /// CeedElemRestriction Backend API
827a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
837a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionBackend
847a982d89SJeremy L. Thompson /// @{
857a982d89SJeremy L. Thompson 
867a982d89SJeremy L. Thompson /**
8778b2e752SJeremy L Thompson   @brief Restrict an L-vector to an E-vector or apply its transpose ignoring any
8878b2e752SJeremy L Thompson          provided orientations
8978b2e752SJeremy L Thompson 
9078b2e752SJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
9178b2e752SJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
9278b2e752SJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
9378b2e752SJeremy L Thompson   @param[out] ru      Output vector (of shape [@a num_elem * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
9478b2e752SJeremy L Thompson                         Ordering of the e-vector is decided by the backend.
9578b2e752SJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
9678b2e752SJeremy L Thompson 
9778b2e752SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
9878b2e752SJeremy L Thompson 
9978b2e752SJeremy L Thompson   @ref User
10078b2e752SJeremy L Thompson **/
10178b2e752SJeremy L Thompson int CeedElemRestrictionApplyUnsigned(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
10278b2e752SJeremy L Thompson   CeedInt m, n;
10378b2e752SJeremy L Thompson 
10478b2e752SJeremy L Thompson   CeedCheck(rstr->ApplyUnsigned, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ElemRestrictionApplyUnsigned");
10578b2e752SJeremy L Thompson 
10678b2e752SJeremy L Thompson   if (t_mode == CEED_NOTRANSPOSE) {
10778b2e752SJeremy L Thompson     m = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
10878b2e752SJeremy L Thompson     n = rstr->l_size;
10978b2e752SJeremy L Thompson   } else {
11078b2e752SJeremy L Thompson     m = rstr->l_size;
11178b2e752SJeremy L Thompson     n = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
11278b2e752SJeremy L Thompson   }
11378b2e752SJeremy L Thompson   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
11478b2e752SJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
11578b2e752SJeremy L Thompson   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
11678b2e752SJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
11778b2e752SJeremy L Thompson   if (rstr->num_elem > 0) CeedCall(rstr->ApplyUnsigned(rstr, t_mode, u, ru, request));
11877d1c127SSebastian Grimberg 
11978b2e752SJeremy L Thompson   return CEED_ERROR_SUCCESS;
12078b2e752SJeremy L Thompson }
12178b2e752SJeremy L Thompson 
12278b2e752SJeremy L Thompson /**
123*fcbe8c06SSebastian Grimberg   @brief Get the type of a CeedElemRestriction
124a681ae63Sjeremylt 
125*fcbe8c06SSebastian Grimberg   @param[in]  rstr      CeedElemRestriction
126*fcbe8c06SSebastian Grimberg   @param[out] rstr_type Variable to store restriction type
127*fcbe8c06SSebastian Grimberg 
128*fcbe8c06SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
129*fcbe8c06SSebastian Grimberg 
130*fcbe8c06SSebastian Grimberg   @ref Backend
131*fcbe8c06SSebastian Grimberg **/
132*fcbe8c06SSebastian Grimberg int CeedElemRestrictionGetType(CeedElemRestriction rstr, CeedRestrictionType *rstr_type) {
133*fcbe8c06SSebastian Grimberg   *rstr_type = rstr->rstr_type;
134*fcbe8c06SSebastian Grimberg   return CEED_ERROR_SUCCESS;
135*fcbe8c06SSebastian Grimberg }
136*fcbe8c06SSebastian Grimberg 
137*fcbe8c06SSebastian Grimberg /**
138*fcbe8c06SSebastian Grimberg   @brief Get the strided status of a CeedElemRestriction
139*fcbe8c06SSebastian Grimberg 
140*fcbe8c06SSebastian Grimberg   @param[in]  rstr       CeedElemRestriction
141*fcbe8c06SSebastian Grimberg   @param[out] is_strided Variable to store strided status, 1 if strided else 0
142*fcbe8c06SSebastian Grimberg **/
143*fcbe8c06SSebastian Grimberg int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) {
144*fcbe8c06SSebastian Grimberg   *is_strided = (rstr->rstr_type == CEED_RESTRICTION_STRIDED);
145*fcbe8c06SSebastian Grimberg   return CEED_ERROR_SUCCESS;
146*fcbe8c06SSebastian Grimberg }
147*fcbe8c06SSebastian Grimberg 
148*fcbe8c06SSebastian Grimberg /**
149a681ae63Sjeremylt   @brief Get the strides of a strided CeedElemRestriction
1507a982d89SJeremy L. Thompson 
151ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
152a681ae63Sjeremylt   @param[out] strides Variable to store strides array
1537a982d89SJeremy L. Thompson 
1547a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1557a982d89SJeremy L. Thompson 
1567a982d89SJeremy L. Thompson   @ref Backend
1577a982d89SJeremy L. Thompson **/
1582b730f8bSJeremy L Thompson int CeedElemRestrictionGetStrides(CeedElemRestriction rstr, CeedInt (*strides)[3]) {
1596574a04fSJeremy L Thompson   CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
1602b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*strides)[i] = rstr->strides[i];
161e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1627a982d89SJeremy L. Thompson }
1637a982d89SJeremy L. Thompson 
1647a982d89SJeremy L. Thompson /**
16577d1c127SSebastian Grimberg   @brief Get the backend stride status of a CeedElemRestriction
16677d1c127SSebastian Grimberg 
16777d1c127SSebastian Grimberg   @param[in]  rstr                 CeedElemRestriction
16877d1c127SSebastian Grimberg   @param[out] has_backend_strides  Variable to store stride status
16977d1c127SSebastian Grimberg 
17077d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
17177d1c127SSebastian Grimberg 
17277d1c127SSebastian Grimberg   @ref Backend
17377d1c127SSebastian Grimberg **/
17477d1c127SSebastian Grimberg int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, bool *has_backend_strides) {
17577d1c127SSebastian Grimberg   CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
17677d1c127SSebastian Grimberg   *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
17777d1c127SSebastian Grimberg                           (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
17877d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
17977d1c127SSebastian Grimberg }
18077d1c127SSebastian Grimberg 
18177d1c127SSebastian Grimberg /**
182bd33150aSjeremylt   @brief Get read-only access to a CeedElemRestriction offsets array by memtype
183bd33150aSjeremylt 
184ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction to retrieve offsets
185*fcbe8c06SSebastian Grimberg   @param[in]  mem_type Memory type on which to access the array.
186*fcbe8c06SSebastian Grimberg                          If the backend uses a different memory type, this will perform a copy (possibly cached).
187d1d35e2fSjeremylt   @param[out] offsets  Array on memory type mem_type
188bd33150aSjeremylt 
189bd33150aSjeremylt   @return An error code: 0 - success, otherwise - failure
190bd33150aSjeremylt 
191bd33150aSjeremylt   @ref User
192bd33150aSjeremylt **/
1932b730f8bSJeremy L Thompson int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) {
194c17ec2beSJeremy L Thompson   if (rstr->rstr_signed) {
195c17ec2beSJeremy L Thompson     CeedCall(CeedElemRestrictionGetOffsets(rstr->rstr_signed, mem_type, offsets));
196c17ec2beSJeremy L Thompson   } else {
1976574a04fSJeremy L Thompson     CeedCheck(rstr->GetOffsets, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetOffsets");
1982b730f8bSJeremy L Thompson     CeedCall(rstr->GetOffsets(rstr, mem_type, offsets));
199d1d35e2fSjeremylt     rstr->num_readers++;
200c17ec2beSJeremy L Thompson   }
201e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
202430758c8SJeremy L Thompson }
203430758c8SJeremy L Thompson 
204430758c8SJeremy L Thompson /**
205430758c8SJeremy L Thompson   @brief Restore an offsets array obtained using CeedElemRestrictionGetOffsets()
206430758c8SJeremy L Thompson 
207ea61e9acSJeremy L Thompson   @param[in] rstr    CeedElemRestriction to restore
208ea61e9acSJeremy L Thompson   @param[in] offsets Array of offset data
209430758c8SJeremy L Thompson 
210430758c8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
211430758c8SJeremy L Thompson 
212430758c8SJeremy L Thompson   @ref User
213430758c8SJeremy L Thompson **/
2142b730f8bSJeremy L Thompson int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr, const CeedInt **offsets) {
215c17ec2beSJeremy L Thompson   if (rstr->rstr_signed) {
216c17ec2beSJeremy L Thompson     CeedCall(CeedElemRestrictionRestoreOffsets(rstr->rstr_signed, offsets));
217c17ec2beSJeremy L Thompson   } else {
218430758c8SJeremy L Thompson     *offsets = NULL;
219d1d35e2fSjeremylt     rstr->num_readers--;
220c17ec2beSJeremy L Thompson   }
221e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
222bd33150aSjeremylt }
223bd33150aSjeremylt 
224bd33150aSjeremylt /**
22577d1c127SSebastian Grimberg   @brief Get read-only access to a CeedElemRestriction orientations array by memtype
2263ac43b2cSJeremy L Thompson 
22777d1c127SSebastian Grimberg   @param[in]  rstr     CeedElemRestriction to retrieve orientations
228*fcbe8c06SSebastian Grimberg   @param[in]  mem_type Memory type on which to access the array.
229*fcbe8c06SSebastian Grimberg                          If the backend uses a different memory type, this will perform a copy (possibly cached).
23077d1c127SSebastian Grimberg   @param[out] orients  Array on memory type mem_type
2313ac43b2cSJeremy L Thompson 
2323ac43b2cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2333ac43b2cSJeremy L Thompson 
23477d1c127SSebastian Grimberg   @ref User
2353ac43b2cSJeremy L Thompson **/
23677d1c127SSebastian Grimberg int CeedElemRestrictionGetOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const bool **orients) {
237*fcbe8c06SSebastian Grimberg   CeedCheck(rstr->GetOrientations, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetOrientations");
23877d1c127SSebastian Grimberg   CeedCall(rstr->GetOrientations(rstr, mem_type, orients));
23977d1c127SSebastian Grimberg   rstr->num_readers++;
240e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2413ac43b2cSJeremy L Thompson }
2423ac43b2cSJeremy L Thompson 
2433ac43b2cSJeremy L Thompson /**
24477d1c127SSebastian Grimberg   @brief Restore an orientations array obtained using CeedElemRestrictionGetOrientations()
245b435c5a6Srezgarshakeri 
24677d1c127SSebastian Grimberg   @param[in] rstr    CeedElemRestriction to restore
24777d1c127SSebastian Grimberg   @param[in] orients Array of orientation data
248b435c5a6Srezgarshakeri 
249b435c5a6Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
250b435c5a6Srezgarshakeri 
25177d1c127SSebastian Grimberg   @ref User
252b435c5a6Srezgarshakeri **/
25377d1c127SSebastian Grimberg int CeedElemRestrictionRestoreOrientations(CeedElemRestriction rstr, const bool **orients) {
25477d1c127SSebastian Grimberg   *orients = NULL;
25577d1c127SSebastian Grimberg   rstr->num_readers--;
256b435c5a6Srezgarshakeri   return CEED_ERROR_SUCCESS;
257b435c5a6Srezgarshakeri }
258b435c5a6Srezgarshakeri 
259b435c5a6Srezgarshakeri /**
26077d1c127SSebastian Grimberg   @brief Get read-only access to a CeedElemRestriction curl-conforming orientations array by memtype
2617a982d89SJeremy L. Thompson 
26277d1c127SSebastian Grimberg   @param[in]  rstr         CeedElemRestriction to retrieve curl-conforming orientations
263*fcbe8c06SSebastian Grimberg   @param[in]  mem_type     Memory type on which to access the array.
264*fcbe8c06SSebastian Grimberg                              If the backend uses a different memory type, this will perform a copy (possibly cached).
26577d1c127SSebastian Grimberg   @param[out] curl_orients Array on memory type mem_type
2667a982d89SJeremy L. Thompson 
2677a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2687a982d89SJeremy L. Thompson 
26977d1c127SSebastian Grimberg   @ref User
2707a982d89SJeremy L. Thompson **/
27177d1c127SSebastian Grimberg int CeedElemRestrictionGetCurlOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **curl_orients) {
272*fcbe8c06SSebastian Grimberg   CeedCheck(rstr->GetCurlOrientations, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetCurlOrientations");
27377d1c127SSebastian Grimberg   CeedCall(rstr->GetCurlOrientations(rstr, mem_type, curl_orients));
27477d1c127SSebastian Grimberg   rstr->num_readers++;
27577d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
27677d1c127SSebastian Grimberg }
27777d1c127SSebastian Grimberg 
27877d1c127SSebastian Grimberg /**
27977d1c127SSebastian Grimberg   @brief Restore an orientations array obtained using CeedElemRestrictionGetCurlOrientations()
28077d1c127SSebastian Grimberg 
28177d1c127SSebastian Grimberg   @param[in] rstr         CeedElemRestriction to restore
28277d1c127SSebastian Grimberg   @param[in] curl_orients Array of orientation data
28377d1c127SSebastian Grimberg 
28477d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
28577d1c127SSebastian Grimberg 
28677d1c127SSebastian Grimberg   @ref User
28777d1c127SSebastian Grimberg **/
28877d1c127SSebastian Grimberg int CeedElemRestrictionRestoreCurlOrientations(CeedElemRestriction rstr, const CeedInt **curl_orients) {
28977d1c127SSebastian Grimberg   *curl_orients = NULL;
29077d1c127SSebastian Grimberg   rstr->num_readers--;
291e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2927a982d89SJeremy L. Thompson }
2937a982d89SJeremy L. Thompson 
2947a982d89SJeremy L. Thompson /**
29549fd234cSJeremy L Thompson 
29649fd234cSJeremy L Thompson   @brief Get the E-vector layout of a CeedElemRestriction
29749fd234cSJeremy L Thompson 
298ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
299*fcbe8c06SSebastian Grimberg   @param[out] layout  Variable to store layout array, stored as [nodes, components, elements].
300*fcbe8c06SSebastian 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]
30149fd234cSJeremy L Thompson 
30249fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
30349fd234cSJeremy L Thompson 
30449fd234cSJeremy L Thompson   @ref Backend
30549fd234cSJeremy L Thompson **/
3062b730f8bSJeremy L Thompson int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, CeedInt (*layout)[3]) {
3076574a04fSJeremy L Thompson   CeedCheck(rstr->layout[0], rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no layout data");
3082b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*layout)[i] = rstr->layout[i];
309e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
31049fd234cSJeremy L Thompson }
31149fd234cSJeremy L Thompson 
31249fd234cSJeremy L Thompson /**
31349fd234cSJeremy L Thompson 
31449fd234cSJeremy L Thompson   @brief Set the E-vector layout of a CeedElemRestriction
31549fd234cSJeremy L Thompson 
316ea61e9acSJeremy L Thompson   @param[in] rstr   CeedElemRestriction
317ea61e9acSJeremy L Thompson   @param[in] layout Variable to containing layout array, stored as [nodes, components, elements].
318ea61e9acSJeremy 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]
31949fd234cSJeremy L Thompson 
32049fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
32149fd234cSJeremy L Thompson 
32249fd234cSJeremy L Thompson   @ref Backend
32349fd234cSJeremy L Thompson **/
3242b730f8bSJeremy L Thompson int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
3252b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) rstr->layout[i] = layout[i];
326e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
32749fd234cSJeremy L Thompson }
32849fd234cSJeremy L Thompson 
32949fd234cSJeremy L Thompson /**
3307a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedElemRestriction
3317a982d89SJeremy L. Thompson 
332ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
3337a982d89SJeremy L. Thompson   @param[out] data Variable to store data
3347a982d89SJeremy L. Thompson 
3357a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3367a982d89SJeremy L. Thompson 
3377a982d89SJeremy L. Thompson   @ref Backend
3387a982d89SJeremy L. Thompson **/
339777ff853SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) {
340777ff853SJeremy L Thompson   *(void **)data = rstr->data;
341e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3427a982d89SJeremy L. Thompson }
3437a982d89SJeremy L. Thompson 
3447a982d89SJeremy L. Thompson /**
3457a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedElemRestriction
3467a982d89SJeremy L. Thompson 
347ea61e9acSJeremy L Thompson   @param[in,out] rstr CeedElemRestriction
348ea61e9acSJeremy L Thompson   @param[in]     data Data to set
3497a982d89SJeremy L. Thompson 
3507a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3517a982d89SJeremy L. Thompson 
3527a982d89SJeremy L. Thompson   @ref Backend
3537a982d89SJeremy L. Thompson **/
354777ff853SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) {
355777ff853SJeremy L Thompson   rstr->data = data;
356e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3577a982d89SJeremy L. Thompson }
3587a982d89SJeremy L. Thompson 
35934359f16Sjeremylt /**
36034359f16Sjeremylt   @brief Increment the reference counter for a CeedElemRestriction
36134359f16Sjeremylt 
362ea61e9acSJeremy L Thompson   @param[in,out] rstr ElemRestriction to increment the reference counter
36334359f16Sjeremylt 
36434359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
36534359f16Sjeremylt 
36634359f16Sjeremylt   @ref Backend
36734359f16Sjeremylt **/
3689560d06aSjeremylt int CeedElemRestrictionReference(CeedElemRestriction rstr) {
36934359f16Sjeremylt   rstr->ref_count++;
37034359f16Sjeremylt   return CEED_ERROR_SUCCESS;
37134359f16Sjeremylt }
37234359f16Sjeremylt 
3736e15d496SJeremy L Thompson /**
3746e15d496SJeremy L Thompson   @brief Estimate number of FLOPs required to apply CeedElemRestriction in t_mode
3756e15d496SJeremy L Thompson 
376ea61e9acSJeremy L Thompson   @param[in]  rstr   ElemRestriction to estimate FLOPs for
377ea61e9acSJeremy L Thompson   @param[in]  t_mode Apply restriction or transpose
378ea61e9acSJeremy L Thompson   @param[out] flops  Address of variable to hold FLOPs estimate
3796e15d496SJeremy L Thompson 
3806e15d496SJeremy L Thompson   @ref Backend
3816e15d496SJeremy L Thompson **/
3822b730f8bSJeremy L Thompson int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedSize *flops) {
38377d1c127SSebastian Grimberg   const bool    *orients      = NULL;
38477d1c127SSebastian Grimberg   const CeedInt *curl_orients = NULL;
3852b730f8bSJeremy L Thompson   CeedInt        e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp, scale = 0;
3866e15d496SJeremy L Thompson 
38777d1c127SSebastian Grimberg   CeedCall(CeedElemRestrictionGetOrientations(rstr, CEED_MEM_HOST, &orients));
38877d1c127SSebastian Grimberg   CeedCall(CeedElemRestrictionGetCurlOrientations(rstr, CEED_MEM_HOST, &curl_orients));
38977d1c127SSebastian Grimberg   if (t_mode == CEED_TRANSPOSE) {
39077d1c127SSebastian Grimberg     if (!orients && !curl_orients) {
39177d1c127SSebastian Grimberg       scale = 1;
39277d1c127SSebastian Grimberg     } else if (!curl_orients) {
39377d1c127SSebastian Grimberg       scale = 2;
39477d1c127SSebastian Grimberg     } else {
39577d1c127SSebastian Grimberg       scale = 6;
3966e15d496SJeremy L Thompson     }
39777d1c127SSebastian Grimberg   } else {
39877d1c127SSebastian Grimberg     if (!orients && !curl_orients) {
39977d1c127SSebastian Grimberg       scale = 0;
40077d1c127SSebastian Grimberg     } else if (!curl_orients) {
40177d1c127SSebastian Grimberg       scale = 1;
40277d1c127SSebastian Grimberg     } else {
40377d1c127SSebastian Grimberg       scale = 5;
40477d1c127SSebastian Grimberg     }
40577d1c127SSebastian Grimberg   }
40677d1c127SSebastian Grimberg   CeedCall(CeedElemRestrictionRestoreOrientations(rstr, &orients));
40777d1c127SSebastian Grimberg   CeedCall(CeedElemRestrictionRestoreCurlOrientations(rstr, &curl_orients));
4086e15d496SJeremy L Thompson   *flops = e_size * scale;
4096e15d496SJeremy L Thompson 
4106e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4116e15d496SJeremy L Thompson }
4126e15d496SJeremy L Thompson 
4137a982d89SJeremy L. Thompson /// @}
4147a982d89SJeremy L. Thompson 
41515910d16Sjeremylt /// @cond DOXYGEN_SKIP
41615910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
41715910d16Sjeremylt /// @endcond
41815910d16Sjeremylt 
4197a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
4207a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
4217a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
4227a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
423d7b241e6Sjeremylt /// @{
424d7b241e6Sjeremylt 
4257a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
42645f1e315Sjeremylt const CeedInt CEED_STRIDES_BACKEND[3] = {0};
4277a982d89SJeremy L. Thompson 
4284cc79fe7SJed Brown /// Indicate that no CeedElemRestriction is provided by the user
4292b730f8bSJeremy L Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = &ceed_elemrestriction_none;
4307a982d89SJeremy L. Thompson 
431d7b241e6Sjeremylt /**
432b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
433d7b241e6Sjeremylt 
434ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
435ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array
436ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
437ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
438*fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
439*fcbe8c06SSebastian 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.
440*fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
441*fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
442ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
443ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
444*fcbe8c06SSebastian Grimberg   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
445*fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
446*fcbe8c06SSebastian Grimberg 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
447ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
448d7b241e6Sjeremylt 
449b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
450dfdf5a53Sjeremylt 
4517a982d89SJeremy L. Thompson   @ref User
452b11c1e72Sjeremylt **/
4532b730f8bSJeremy L Thompson int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
4542b730f8bSJeremy L Thompson                               CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
4555fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
4565fe0d4faSjeremylt     Ceed delegate;
4576574a04fSJeremy L Thompson 
4582b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
45977d1c127SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
4602b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
461e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
4625fe0d4faSjeremylt   }
4635fe0d4faSjeremylt 
4646574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
4656574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
4666574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
467e022e1f8SJeremy L Thompson 
4682b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
469db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
470d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
471d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
472d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
473d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
474d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
475d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
476d1d35e2fSjeremylt   (*rstr)->num_blk     = num_elem;
477d1d35e2fSjeremylt   (*rstr)->blk_size    = 1;
478*fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_DEFAULT;
479*fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, NULL, *rstr));
480e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
481d7b241e6Sjeremylt }
482d7b241e6Sjeremylt 
483d7b241e6Sjeremylt /**
48477d1c127SSebastian Grimberg   @brief Create a CeedElemRestriction with orientation signs
485fc0567d9Srezgarshakeri 
486ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
487ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array
488ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
489ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
490*fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
491*fcbe8c06SSebastian 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.
492*fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
493*fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
494ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
495ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
496*fcbe8c06SSebastian Grimberg   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
497*fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
498*fcbe8c06SSebastian Grimberg 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
49977d1c127SSebastian 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.
500ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
501fc0567d9Srezgarshakeri 
502fc0567d9Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
503fc0567d9Srezgarshakeri 
504fc0567d9Srezgarshakeri   @ref User
505fc0567d9Srezgarshakeri **/
5062b730f8bSJeremy L Thompson int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
50777d1c127SSebastian Grimberg                                       CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orients,
508fc0567d9Srezgarshakeri                                       CeedElemRestriction *rstr) {
509*fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreate) {
510fc0567d9Srezgarshakeri     Ceed delegate;
5116574a04fSJeremy L Thompson 
5122b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
513*fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
5142b730f8bSJeremy L Thompson     CeedCall(
51577d1c127SSebastian Grimberg         CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, orients, rstr));
516fc0567d9Srezgarshakeri     return CEED_ERROR_SUCCESS;
517fc0567d9Srezgarshakeri   }
518fc0567d9Srezgarshakeri 
5196574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
5206574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
5216574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
522e022e1f8SJeremy L Thompson 
5232b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
524db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
525fc0567d9Srezgarshakeri   (*rstr)->ref_count   = 1;
526fc0567d9Srezgarshakeri   (*rstr)->num_elem    = num_elem;
527fc0567d9Srezgarshakeri   (*rstr)->elem_size   = elem_size;
528fc0567d9Srezgarshakeri   (*rstr)->num_comp    = num_comp;
529fc0567d9Srezgarshakeri   (*rstr)->comp_stride = comp_stride;
530fc0567d9Srezgarshakeri   (*rstr)->l_size      = l_size;
531fc0567d9Srezgarshakeri   (*rstr)->num_blk     = num_elem;
532fc0567d9Srezgarshakeri   (*rstr)->blk_size    = 1;
533*fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_ORIENTED;
534*fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, orients, NULL, *rstr));
53577d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
53677d1c127SSebastian Grimberg }
53777d1c127SSebastian Grimberg 
53877d1c127SSebastian Grimberg /**
53977d1c127SSebastian Grimberg   @brief Create a CeedElemRestriction with a general tridiagonal transformation matrix for curl-conforming elements
54077d1c127SSebastian Grimberg 
54177d1c127SSebastian Grimberg   @param[in]  ceed         Ceed object where the CeedElemRestriction will be created
54277d1c127SSebastian Grimberg   @param[in]  num_elem     Number of elements described in the @a offsets array
54377d1c127SSebastian Grimberg   @param[in]  elem_size    Size (number of "nodes") per element
54477d1c127SSebastian Grimberg   @param[in]  num_comp     Number of field components per interpolation node (1 for scalar fields)
545*fcbe8c06SSebastian Grimberg   @param[in]  comp_stride  Stride between components for the same L-vector "node".
546*fcbe8c06SSebastian 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.
547*fcbe8c06SSebastian Grimberg   @param[in]  l_size       The size of the L-vector.
548*fcbe8c06SSebastian Grimberg                              This vector may be larger than the elements and fields given by this restriction.
54977d1c127SSebastian Grimberg   @param[in]  mem_type     Memory type of the @a offsets array, see CeedMemType
55077d1c127SSebastian Grimberg   @param[in]  copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
551*fcbe8c06SSebastian Grimberg   @param[in]  offsets      Array of shape [@a num_elem, @a elem_size].
552*fcbe8c06SSebastian Grimberg                              Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i,
553*fcbe8c06SSebastian Grimberg where 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
55477d1c127SSebastian Grimberg   @param[in]  curl_orients Array of shape [@a num_elem, @a 3 * elem_size] representing a row-major tridiagonal matrix (curl_orients[0] =
55577d1c127SSebastian 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
55677d1c127SSebastian 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
55777d1c127SSebastian Grimberg to resolve face orientation issues for 3D meshes (https://dl.acm.org/doi/pdf/10.1145/3524456).
55877d1c127SSebastian Grimberg   @param[out] rstr         Address of the variable where the newly created CeedElemRestriction will be stored
55977d1c127SSebastian Grimberg 
56077d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
56177d1c127SSebastian Grimberg 
56277d1c127SSebastian Grimberg   @ref User
56377d1c127SSebastian Grimberg **/
56477d1c127SSebastian Grimberg int CeedElemRestrictionCreateCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
56577d1c127SSebastian Grimberg                                           CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const CeedInt *curl_orients,
56677d1c127SSebastian Grimberg                                           CeedElemRestriction *rstr) {
567*fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreate) {
56877d1c127SSebastian Grimberg     Ceed delegate;
56977d1c127SSebastian Grimberg 
57077d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
571*fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
57277d1c127SSebastian Grimberg     CeedCall(CeedElemRestrictionCreateCurlOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
57377d1c127SSebastian Grimberg                                                    curl_orients, rstr));
57477d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
57577d1c127SSebastian Grimberg   }
57677d1c127SSebastian Grimberg 
57777d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
57877d1c127SSebastian Grimberg   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
57977d1c127SSebastian Grimberg   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
58077d1c127SSebastian Grimberg 
58177d1c127SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
582*fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
58377d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
58477d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
58577d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
58677d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
58777d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
58877d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
58977d1c127SSebastian Grimberg   (*rstr)->num_blk     = num_elem;
59077d1c127SSebastian Grimberg   (*rstr)->blk_size    = 1;
591*fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_CURL_ORIENTED;
592*fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, curl_orients, *rstr));
593fc0567d9Srezgarshakeri   return CEED_ERROR_SUCCESS;
594fc0567d9Srezgarshakeri }
595fc0567d9Srezgarshakeri 
596fc0567d9Srezgarshakeri /**
5977509a596Sjeremylt   @brief Create a strided CeedElemRestriction
598d7b241e6Sjeremylt 
599ea61e9acSJeremy L Thompson   @param[in]  ceed      Ceed object where the CeedElemRestriction will be created
600ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
601ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
602ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation "node" (1 for scalar fields)
603*fcbe8c06SSebastian Grimberg   @param[in]  l_size    The size of the L-vector.
604*fcbe8c06SSebastian Grimberg                           This vector may be larger than the elements and fields given by this restriction.
605*fcbe8c06SSebastian Grimberg   @param[in]  strides   Array for strides between [nodes, components, elements].
606*fcbe8c06SSebastian 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].
607*fcbe8c06SSebastian Grimberg                           @a CEED_STRIDES_BACKEND may be used with vectors created by a Ceed backend.
608ea61e9acSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created CeedElemRestriction will be stored
609d7b241e6Sjeremylt 
610b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
611dfdf5a53Sjeremylt 
6127a982d89SJeremy L. Thompson   @ref User
613b11c1e72Sjeremylt **/
6142b730f8bSJeremy L Thompson int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedSize l_size, const CeedInt strides[3],
615f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
6165fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
6175fe0d4faSjeremylt     Ceed delegate;
618b04eb3d9SSebastian Grimberg 
6192b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
620*fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
6212b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, l_size, strides, rstr));
622e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6235fe0d4faSjeremylt   }
6245fe0d4faSjeremylt 
6256574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
6266574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
627e022e1f8SJeremy L Thompson 
6282b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
629db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
630d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
631d1d35e2fSjeremylt   (*rstr)->num_elem  = num_elem;
632d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
633d1d35e2fSjeremylt   (*rstr)->num_comp  = num_comp;
634d1d35e2fSjeremylt   (*rstr)->l_size    = l_size;
635d1d35e2fSjeremylt   (*rstr)->num_blk   = num_elem;
636d1d35e2fSjeremylt   (*rstr)->blk_size  = 1;
637*fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type = CEED_RESTRICTION_STRIDED;
6382b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
6392b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
640*fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
641e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
642d7b241e6Sjeremylt }
643d7b241e6Sjeremylt 
644d7b241e6Sjeremylt /**
645b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
646d7b241e6Sjeremylt 
647ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created.
648ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array.
649ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of unknowns) per element
650ea61e9acSJeremy L Thompson   @param[in]  blk_size    Number of elements in a block
651ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
652*fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
653*fcbe8c06SSebastian 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.
654*fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
655*fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
656ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
657ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
658*fcbe8c06SSebastian Grimberg   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
659*fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
660*fcbe8c06SSebastian 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
661*fcbe8c06SSebastian Grimberg  the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
662ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
663d7b241e6Sjeremylt 
664b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
665dfdf5a53Sjeremylt 
6667a982d89SJeremy L. Thompson   @ref Backend
667b11c1e72Sjeremylt  **/
6682b730f8bSJeremy L Thompson int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedInt comp_stride,
6692b730f8bSJeremy L Thompson                                      CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets,
6704ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
671d1d35e2fSjeremylt   CeedInt *blk_offsets;
672d1d35e2fSjeremylt   CeedInt  num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
673d7b241e6Sjeremylt 
6745fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
6755fe0d4faSjeremylt     Ceed delegate;
6766574a04fSJeremy L Thompson 
6772b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
6786402da51SJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
6792b730f8bSJeremy L Thompson     CeedCall(
6802b730f8bSJeremy L Thompson         CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, blk_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
681e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6825fe0d4faSjeremylt   }
683d7b241e6Sjeremylt 
6846574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
6856574a04fSJeremy L Thompson   CeedCheck(blk_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
6866574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
6876574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
688e022e1f8SJeremy L Thompson 
6892b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(num_blk * blk_size * elem_size, &blk_offsets));
6902b730f8bSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size, elem_size));
691d7b241e6Sjeremylt 
692db002c03SJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
693db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
694d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
695d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
696d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
697d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
698d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
699d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
700d1d35e2fSjeremylt   (*rstr)->num_blk     = num_blk;
701d1d35e2fSjeremylt   (*rstr)->blk_size    = blk_size;
702*fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_DEFAULT;
703*fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)blk_offsets, NULL, NULL, *rstr));
704d1d35e2fSjeremylt   if (copy_mode == CEED_OWN_POINTER) {
7052b730f8bSJeremy L Thompson     CeedCall(CeedFree(&offsets));
7061d102b48SJeremy L Thompson   }
707e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
708d7b241e6Sjeremylt }
709d7b241e6Sjeremylt 
710b11c1e72Sjeremylt /**
71177d1c127SSebastian Grimberg   @brief Create a blocked oriented CeedElemRestriction, typically only called by backends
71277d1c127SSebastian Grimberg 
71377d1c127SSebastian Grimberg   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created.
71477d1c127SSebastian Grimberg   @param[in]  num_elem    Number of elements described in the @a offsets array.
71577d1c127SSebastian Grimberg   @param[in]  elem_size   Size (number of unknowns) per element
71677d1c127SSebastian Grimberg   @param[in]  blk_size    Number of elements in a block
71777d1c127SSebastian Grimberg   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
718*fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
719*fcbe8c06SSebastian 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.
720*fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
721*fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
72277d1c127SSebastian Grimberg   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
72377d1c127SSebastian Grimberg   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
724*fcbe8c06SSebastian Grimberg   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
725*fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
726*fcbe8c06SSebastian 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
727*fcbe8c06SSebastian Grimberg  the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
728*fcbe8c06SSebastian 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.
729*fcbe8c06SSebastian Grimberg                             Will also be permuted and padded similarly to @a offsets.
73077d1c127SSebastian Grimberg   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
73177d1c127SSebastian Grimberg 
73277d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
73377d1c127SSebastian Grimberg 
73477d1c127SSebastian Grimberg   @ref Backend
73577d1c127SSebastian Grimberg  **/
73677d1c127SSebastian Grimberg int CeedElemRestrictionCreateBlockedOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedInt comp_stride,
73777d1c127SSebastian Grimberg                                              CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets,
73877d1c127SSebastian Grimberg                                              const bool *orients, CeedElemRestriction *rstr) {
73977d1c127SSebastian Grimberg   CeedInt *blk_offsets;
74077d1c127SSebastian Grimberg   bool    *blk_orients;
74177d1c127SSebastian Grimberg   CeedInt  num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
74277d1c127SSebastian Grimberg 
743*fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreateBlocked) {
74477d1c127SSebastian Grimberg     Ceed delegate;
74577d1c127SSebastian Grimberg 
74677d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
747*fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
74877d1c127SSebastian Grimberg     CeedCall(CeedElemRestrictionCreateBlockedOriented(delegate, num_elem, elem_size, blk_size, num_comp, comp_stride, l_size, mem_type, copy_mode,
74977d1c127SSebastian Grimberg                                                       offsets, orients, rstr));
75077d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
75177d1c127SSebastian Grimberg   }
75277d1c127SSebastian Grimberg 
75377d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
75477d1c127SSebastian Grimberg   CeedCheck(blk_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
75577d1c127SSebastian Grimberg   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
75677d1c127SSebastian Grimberg   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
75777d1c127SSebastian Grimberg 
75877d1c127SSebastian Grimberg   CeedCall(CeedCalloc(num_blk * blk_size * elem_size, &blk_offsets));
75977d1c127SSebastian Grimberg   CeedCall(CeedCalloc(num_blk * blk_size * elem_size, &blk_orients));
76077d1c127SSebastian Grimberg   CeedCall(CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size, elem_size));
76177d1c127SSebastian Grimberg   CeedCall(CeedPermutePadOrientations(orients, blk_orients, num_blk, num_elem, blk_size, elem_size));
76277d1c127SSebastian Grimberg 
763*fcbe8c06SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
764*fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
76577d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
76677d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
76777d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
76877d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
76977d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
77077d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
77177d1c127SSebastian Grimberg   (*rstr)->num_blk     = num_blk;
77277d1c127SSebastian Grimberg   (*rstr)->blk_size    = blk_size;
773*fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_ORIENTED;
774*fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)blk_offsets, (const bool *)blk_orients, NULL, *rstr));
77577d1c127SSebastian Grimberg   if (copy_mode == CEED_OWN_POINTER) {
77677d1c127SSebastian Grimberg     CeedCall(CeedFree(&offsets));
77777d1c127SSebastian Grimberg   }
77877d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
77977d1c127SSebastian Grimberg }
78077d1c127SSebastian Grimberg 
78177d1c127SSebastian Grimberg /**
78277d1c127SSebastian Grimberg   @brief Create a blocked curl-oriented CeedElemRestriction, typically only called by backends
78377d1c127SSebastian Grimberg 
78477d1c127SSebastian Grimberg   @param[in]  ceed         Ceed object where the CeedElemRestriction will be created.
78577d1c127SSebastian Grimberg   @param[in]  num_elem     Number of elements described in the @a offsets array.
78677d1c127SSebastian Grimberg   @param[in]  elem_size    Size (number of unknowns) per element
78777d1c127SSebastian Grimberg   @param[in]  blk_size     Number of elements in a block
78877d1c127SSebastian Grimberg   @param[in]  num_comp     Number of field components per interpolation node (1 for scalar fields)
789*fcbe8c06SSebastian Grimberg   @param[in]  comp_stride  Stride between components for the same L-vector "node".
790*fcbe8c06SSebastian 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.
791*fcbe8c06SSebastian Grimberg   @param[in]  l_size       The size of the L-vector.
792*fcbe8c06SSebastian Grimberg                              This vector may be larger than the elements and fields given by this restriction.
79377d1c127SSebastian Grimberg   @param[in]  mem_type     Memory type of the @a offsets array, see CeedMemType
79477d1c127SSebastian Grimberg   @param[in]  copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
795*fcbe8c06SSebastian Grimberg   @param[in]  offsets      Array of shape [@a num_elem, @a elem_size].
796*fcbe8c06SSebastian Grimberg                              Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i,
797*fcbe8c06SSebastian 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
798*fcbe8c06SSebastian Grimberg for the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
79977d1c127SSebastian Grimberg   @param[in]  curl_orients Array of shape [@a num_elem, @a 3 * elem_size] representing a row-major tridiagonal matrix (curl_orients[0] =
800*fcbe8c06SSebastian 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.
801*fcbe8c06SSebastian Grimberg                              This orientation matrix allows for pairs of face degrees of freedom on elements for H(curl) spaces to be coupled in the
802*fcbe8c06SSebastian 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
803*fcbe8c06SSebastian Grimberg be permuted and padded similarly to @a offsets.
80477d1c127SSebastian Grimberg   @param[out] rstr         Address of the variable where the newly created CeedElemRestriction will be stored
80577d1c127SSebastian Grimberg 
80677d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
80777d1c127SSebastian Grimberg 
80877d1c127SSebastian Grimberg   @ref Backend
80977d1c127SSebastian Grimberg  **/
81077d1c127SSebastian Grimberg int CeedElemRestrictionCreateBlockedCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp,
81177d1c127SSebastian Grimberg                                                  CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode,
81277d1c127SSebastian Grimberg                                                  const CeedInt *offsets, const CeedInt *curl_orients, CeedElemRestriction *rstr) {
81377d1c127SSebastian Grimberg   CeedInt *blk_offsets;
81477d1c127SSebastian Grimberg   CeedInt *blk_curl_orients;
81577d1c127SSebastian Grimberg   CeedInt  num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
81677d1c127SSebastian Grimberg 
817*fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreateBlocked) {
81877d1c127SSebastian Grimberg     Ceed delegate;
81977d1c127SSebastian Grimberg 
82077d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
821*fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
82277d1c127SSebastian Grimberg     CeedCall(CeedElemRestrictionCreateBlockedCurlOriented(delegate, num_elem, elem_size, blk_size, num_comp, comp_stride, l_size, mem_type, copy_mode,
82377d1c127SSebastian Grimberg                                                           offsets, curl_orients, rstr));
82477d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
82577d1c127SSebastian Grimberg   }
82677d1c127SSebastian Grimberg 
82777d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
82877d1c127SSebastian Grimberg   CeedCheck(blk_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
82977d1c127SSebastian Grimberg   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
83077d1c127SSebastian Grimberg   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
83177d1c127SSebastian Grimberg 
83277d1c127SSebastian Grimberg   CeedCall(CeedCalloc(num_blk * blk_size * elem_size, &blk_offsets));
83377d1c127SSebastian Grimberg   CeedCall(CeedCalloc(num_blk * blk_size * 3 * elem_size, &blk_curl_orients));
83477d1c127SSebastian Grimberg   CeedCall(CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size, elem_size));
83577d1c127SSebastian Grimberg   CeedCall(CeedPermutePadOffsets(curl_orients, blk_curl_orients, num_blk, num_elem, blk_size, 3 * elem_size));
83677d1c127SSebastian Grimberg 
837*fcbe8c06SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
838*fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
83977d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
84077d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
84177d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
84277d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
84377d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
84477d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
84577d1c127SSebastian Grimberg   (*rstr)->num_blk     = num_blk;
84677d1c127SSebastian Grimberg   (*rstr)->blk_size    = blk_size;
847*fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_CURL_ORIENTED;
848*fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)blk_offsets, NULL, (const CeedInt *)blk_curl_orients,
849*fcbe8c06SSebastian Grimberg                                               *rstr));
85077d1c127SSebastian Grimberg   if (copy_mode == CEED_OWN_POINTER) {
85177d1c127SSebastian Grimberg     CeedCall(CeedFree(&offsets));
85277d1c127SSebastian Grimberg   }
85377d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
85477d1c127SSebastian Grimberg }
85577d1c127SSebastian Grimberg 
85677d1c127SSebastian Grimberg /**
85777d1c127SSebastian Grimberg   @brief Create a blocked strided CeedElemRestriction, typically only called by backends
8587509a596Sjeremylt 
859ea61e9acSJeremy L Thompson   @param[in]  ceed      Ceed object where the CeedElemRestriction will be created
860ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
861ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
862ea61e9acSJeremy L Thompson   @param[in]  blk_size  Number of elements in a block
863ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation node (1 for scalar fields)
864*fcbe8c06SSebastian Grimberg   @param[in]  l_size    The size of the L-vector.
865*fcbe8c06SSebastian Grimberg                           This vector may be larger than the elements and fields given by this restriction.
866*fcbe8c06SSebastian Grimberg   @param[in]  strides   Array for strides between [nodes, components, elements].
867*fcbe8c06SSebastian 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].
868*fcbe8c06SSebastian Grimberg                           @a CEED_STRIDES_BACKEND may be used with vectors created by a Ceed backend.
869ea61e9acSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created CeedElemRestriction will be stored
8707509a596Sjeremylt 
8717509a596Sjeremylt   @return An error code: 0 - success, otherwise - failure
8727509a596Sjeremylt 
8737a982d89SJeremy L. Thompson   @ref User
8747509a596Sjeremylt **/
8752b730f8bSJeremy L Thompson int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedSize l_size,
8768621c6c6SJeremy L Thompson                                             const CeedInt strides[3], CeedElemRestriction *rstr) {
877d1d35e2fSjeremylt   CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size);
8787509a596Sjeremylt 
8797509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
8807509a596Sjeremylt     Ceed delegate;
8816574a04fSJeremy L Thompson 
8822b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
883*fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
8842b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, blk_size, num_comp, l_size, strides, rstr));
885e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
8867509a596Sjeremylt   }
8877509a596Sjeremylt 
8886574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
8896574a04fSJeremy L Thompson   CeedCheck(blk_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
8906574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
891e022e1f8SJeremy L Thompson 
8922b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
893db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
894d1d35e2fSjeremylt   (*rstr)->ref_count = 1;
895d1d35e2fSjeremylt   (*rstr)->num_elem  = num_elem;
896d1d35e2fSjeremylt   (*rstr)->elem_size = elem_size;
897d1d35e2fSjeremylt   (*rstr)->num_comp  = num_comp;
898d1d35e2fSjeremylt   (*rstr)->l_size    = l_size;
899d1d35e2fSjeremylt   (*rstr)->num_blk   = num_blk;
900d1d35e2fSjeremylt   (*rstr)->blk_size  = blk_size;
901*fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type = CEED_RESTRICTION_STRIDED;
9022b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
9032b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
904*fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
905e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
9067509a596Sjeremylt }
9077509a596Sjeremylt 
9087509a596Sjeremylt /**
909c17ec2beSJeremy L Thompson   @brief Copy the pointer to a CeedElemRestriction and set `CeedElemRestrictionApply()` implementation to `CeedElemRestrictionApplyUnsigned()`.
910c17ec2beSJeremy L Thompson 
911c17ec2beSJeremy L Thompson   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
912c17ec2beSJeremy L Thompson 
913c17ec2beSJeremy L Thompson   @param[in]     rstr          CeedElemRestriction to create unsigned reference to
914c17ec2beSJeremy L Thompson   @param[in,out] rstr_unsigned Variable to store unsigned CeedElemRestriction
915c17ec2beSJeremy L Thompson 
916c17ec2beSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
917c17ec2beSJeremy L Thompson 
918c17ec2beSJeremy L Thompson   @ref User
919c17ec2beSJeremy L Thompson **/
920c17ec2beSJeremy L Thompson int CeedElemRestrictionCreateUnsignedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unsigned) {
921c17ec2beSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr_unsigned));
922c17ec2beSJeremy L Thompson 
923c17ec2beSJeremy L Thompson   // Copy old rstr
924c17ec2beSJeremy L Thompson   memcpy(*rstr_unsigned, rstr, sizeof(struct CeedElemRestriction_private));
925c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ceed = NULL;
926c17ec2beSJeremy L Thompson   CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unsigned)->ceed));
927c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ref_count = 1;
928c17ec2beSJeremy L Thompson   (*rstr_unsigned)->strides   = NULL;
929c17ec2beSJeremy L Thompson   if (rstr->strides) {
930c17ec2beSJeremy L Thompson     CeedCall(CeedMalloc(3, &(*rstr_unsigned)->strides));
931c17ec2beSJeremy L Thompson     for (CeedInt i = 0; i < 3; i++) (*rstr_unsigned)->strides[i] = rstr->strides[i];
932c17ec2beSJeremy L Thompson   }
933c17ec2beSJeremy L Thompson   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unsigned)->rstr_signed));
934c17ec2beSJeremy L Thompson 
935c17ec2beSJeremy L Thompson   // Override Apply
936c17ec2beSJeremy L Thompson   (*rstr_unsigned)->Apply = rstr->ApplyUnsigned;
937c17ec2beSJeremy L Thompson 
938c17ec2beSJeremy L Thompson   return CEED_ERROR_SUCCESS;
939c17ec2beSJeremy L Thompson }
940c17ec2beSJeremy L Thompson 
941c17ec2beSJeremy L Thompson /**
942ea61e9acSJeremy L Thompson   @brief Copy the pointer to a CeedElemRestriction.
9439fd66db6SSebastian Grimberg 
944ea61e9acSJeremy L Thompson   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
9459560d06aSjeremylt 
9469fd66db6SSebastian 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.
9479fd66db6SSebastian Grimberg         This CeedElemRestriction will be destroyed if `rstr_copy` is the only reference to this CeedElemRestriction.
948ea61e9acSJeremy L Thompson 
949ea61e9acSJeremy L Thompson   @param[in]     rstr      CeedElemRestriction to copy reference to
950ea61e9acSJeremy L Thompson   @param[in,out] rstr_copy Variable to store copied reference
9519560d06aSjeremylt 
9529560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
9539560d06aSjeremylt 
9549560d06aSjeremylt   @ref User
9559560d06aSjeremylt **/
9562b730f8bSJeremy L Thompson int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_copy) {
957393ac2cdSJeremy L Thompson   if (rstr != CEED_ELEMRESTRICTION_NONE) CeedCall(CeedElemRestrictionReference(rstr));
9582b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionDestroy(rstr_copy));
9599560d06aSjeremylt   *rstr_copy = rstr;
9609560d06aSjeremylt   return CEED_ERROR_SUCCESS;
9619560d06aSjeremylt }
9629560d06aSjeremylt 
9639560d06aSjeremylt /**
964b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
965b11c1e72Sjeremylt 
966ea61e9acSJeremy L Thompson   @param[in]  rstr  CeedElemRestriction
967ea61e9acSJeremy L Thompson   @param[out] l_vec The address of the L-vector to be created, or NULL
968ea61e9acSJeremy L Thompson   @param[out] e_vec The address of the E-vector to be created, or NULL
969b11c1e72Sjeremylt 
970b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
971dfdf5a53Sjeremylt 
9727a982d89SJeremy L. Thompson   @ref User
973b11c1e72Sjeremylt **/
9742b730f8bSJeremy L Thompson int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, CeedVector *e_vec) {
975d2643443SJeremy L Thompson   CeedSize e_size, l_size;
976d1d35e2fSjeremylt   l_size = rstr->l_size;
977d1d35e2fSjeremylt   e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
9782b730f8bSJeremy L Thompson   if (l_vec) CeedCall(CeedVectorCreate(rstr->ceed, l_size, l_vec));
9792b730f8bSJeremy L Thompson   if (e_vec) CeedCall(CeedVectorCreate(rstr->ceed, e_size, e_vec));
980e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
981d7b241e6Sjeremylt }
982d7b241e6Sjeremylt 
983d7b241e6Sjeremylt /**
984d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
985d7b241e6Sjeremylt 
986ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
987ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
988ea61e9acSJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
989*fcbe8c06SSebastian Grimberg   @param[out] ru      Output vector (of shape [@a num_elem * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
990*fcbe8c06SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
991ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
992b11c1e72Sjeremylt 
993b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
994dfdf5a53Sjeremylt 
9957a982d89SJeremy L. Thompson   @ref User
996b11c1e72Sjeremylt **/
9972b730f8bSJeremy L Thompson int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
998d7b241e6Sjeremylt   CeedInt m, n;
999d7b241e6Sjeremylt 
1000d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
1001d1d35e2fSjeremylt     m = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
1002d1d35e2fSjeremylt     n = rstr->l_size;
1003d7b241e6Sjeremylt   } else {
1004d1d35e2fSjeremylt     m = rstr->l_size;
1005d1d35e2fSjeremylt     n = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp;
1006d7b241e6Sjeremylt   }
10076574a04fSJeremy L Thompson   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
10086574a04fSJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
10096574a04fSJeremy L Thompson   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
10106574a04fSJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
10112b730f8bSJeremy L Thompson   if (rstr->num_elem > 0) CeedCall(rstr->Apply(rstr, t_mode, u, ru, request));
1012e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1013d7b241e6Sjeremylt }
1014d7b241e6Sjeremylt 
1015d7b241e6Sjeremylt /**
1016d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
1017be9261b7Sjeremylt 
1018ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
1019ea61e9acSJeremy 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
1020ea61e9acSJeremy L Thompson : 4*blk_size]
1021ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1022ea61e9acSJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
1023*fcbe8c06SSebastian Grimberg   @param[out] ru      Output vector (of shape [@a blk_size * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
1024*fcbe8c06SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
1025ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
1026be9261b7Sjeremylt 
1027be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
1028be9261b7Sjeremylt 
10297a982d89SJeremy L. Thompson   @ref Backend
1030be9261b7Sjeremylt **/
10312b730f8bSJeremy L Thompson int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
10322b730f8bSJeremy L Thompson                                   CeedRequest *request) {
1033be9261b7Sjeremylt   CeedInt m, n;
1034be9261b7Sjeremylt 
10356402da51SJeremy L Thompson   CeedCheck(rstr->ApplyBlock, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionApplyBlock");
10366402da51SJeremy L Thompson 
1037d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
1038d1d35e2fSjeremylt     m = rstr->blk_size * rstr->elem_size * rstr->num_comp;
1039d1d35e2fSjeremylt     n = rstr->l_size;
1040be9261b7Sjeremylt   } else {
1041d1d35e2fSjeremylt     m = rstr->l_size;
1042d1d35e2fSjeremylt     n = rstr->blk_size * rstr->elem_size * rstr->num_comp;
1043be9261b7Sjeremylt   }
10446574a04fSJeremy L Thompson   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
10456574a04fSJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
10466574a04fSJeremy L Thompson   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
10476574a04fSJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
10486574a04fSJeremy L Thompson   CeedCheck(rstr->blk_size * block <= rstr->num_elem, rstr->ceed, CEED_ERROR_DIMENSION,
10496574a04fSJeremy L Thompson             "Cannot retrieve block %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", block, rstr->blk_size * block,
10506574a04fSJeremy L Thompson             rstr->num_elem);
10512b730f8bSJeremy L Thompson   CeedCall(rstr->ApplyBlock(rstr, block, t_mode, u, ru, request));
1052e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1053be9261b7Sjeremylt }
1054be9261b7Sjeremylt 
1055be9261b7Sjeremylt /**
1056b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedElemRestriction
1057b7c9bbdaSJeremy L Thompson 
1058ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
1059b7c9bbdaSJeremy L Thompson   @param[out] ceed Variable to store Ceed
1060b7c9bbdaSJeremy L Thompson 
1061b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1062b7c9bbdaSJeremy L Thompson 
1063b7c9bbdaSJeremy L Thompson   @ref Advanced
1064b7c9bbdaSJeremy L Thompson **/
1065b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
1066b7c9bbdaSJeremy L Thompson   *ceed = rstr->ceed;
1067b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1068b7c9bbdaSJeremy L Thompson }
1069b7c9bbdaSJeremy L Thompson 
1070b7c9bbdaSJeremy L Thompson /**
1071d979a051Sjeremylt   @brief Get the L-vector component stride
1072a681ae63Sjeremylt 
1073ea61e9acSJeremy L Thompson   @param[in]  rstr        CeedElemRestriction
1074d1d35e2fSjeremylt   @param[out] comp_stride Variable to store component stride
1075a681ae63Sjeremylt 
1076a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1077a681ae63Sjeremylt 
1078b7c9bbdaSJeremy L Thompson   @ref Advanced
1079a681ae63Sjeremylt **/
10802b730f8bSJeremy L Thompson int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, CeedInt *comp_stride) {
1081d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
1082e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1083a681ae63Sjeremylt }
1084a681ae63Sjeremylt 
1085a681ae63Sjeremylt /**
1086a681ae63Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
1087a681ae63Sjeremylt 
1088ea61e9acSJeremy L Thompson   @param[in] rstr      CeedElemRestriction
1089d1d35e2fSjeremylt   @param[out] num_elem Variable to store number of elements
1090a681ae63Sjeremylt 
1091a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1092a681ae63Sjeremylt 
1093b7c9bbdaSJeremy L Thompson   @ref Advanced
1094a681ae63Sjeremylt **/
10952b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, CeedInt *num_elem) {
1096d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
1097e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1098a681ae63Sjeremylt }
1099a681ae63Sjeremylt 
1100a681ae63Sjeremylt /**
1101a681ae63Sjeremylt   @brief Get the size of elements in the CeedElemRestriction
1102a681ae63Sjeremylt 
1103ea61e9acSJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
1104d1d35e2fSjeremylt   @param[out] elem_size Variable to store size of elements
1105a681ae63Sjeremylt 
1106a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1107a681ae63Sjeremylt 
1108b7c9bbdaSJeremy L Thompson   @ref Advanced
1109a681ae63Sjeremylt **/
11102b730f8bSJeremy L Thompson int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, CeedInt *elem_size) {
1111d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
1112e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1113a681ae63Sjeremylt }
1114a681ae63Sjeremylt 
1115a681ae63Sjeremylt /**
1116d979a051Sjeremylt   @brief Get the size of the l-vector for a CeedElemRestriction
1117a681ae63Sjeremylt 
1118ea61e9acSJeremy L Thompson   @param[in]  rstr   CeedElemRestriction
1119d1d35e2fSjeremylt   @param[out] l_size Variable to store number of nodes
1120a681ae63Sjeremylt 
1121a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1122a681ae63Sjeremylt 
1123b7c9bbdaSJeremy L Thompson   @ref Advanced
1124a681ae63Sjeremylt **/
11252b730f8bSJeremy L Thompson int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, CeedSize *l_size) {
1126d1d35e2fSjeremylt   *l_size = rstr->l_size;
1127e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1128a681ae63Sjeremylt }
1129a681ae63Sjeremylt 
1130a681ae63Sjeremylt /**
1131ea61e9acSJeremy L Thompson   @brief Get the number of components in the elements of a CeedElemRestriction
1132a681ae63Sjeremylt 
1133ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction
1134d1d35e2fSjeremylt   @param[out] num_comp Variable to store number of components
1135a681ae63Sjeremylt 
1136a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1137a681ae63Sjeremylt 
1138b7c9bbdaSJeremy L Thompson   @ref Advanced
1139a681ae63Sjeremylt **/
11402b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, CeedInt *num_comp) {
1141d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
1142e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1143a681ae63Sjeremylt }
1144a681ae63Sjeremylt 
1145a681ae63Sjeremylt /**
1146a681ae63Sjeremylt   @brief Get the number of blocks in a CeedElemRestriction
1147a681ae63Sjeremylt 
1148ea61e9acSJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
1149d1d35e2fSjeremylt   @param[out] num_block Variable to store number of blocks
1150a681ae63Sjeremylt 
1151a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1152a681ae63Sjeremylt 
1153b7c9bbdaSJeremy L Thompson   @ref Advanced
1154a681ae63Sjeremylt **/
11552b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, CeedInt *num_block) {
1156d1d35e2fSjeremylt   *num_block = rstr->num_blk;
1157e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1158a681ae63Sjeremylt }
1159a681ae63Sjeremylt 
1160a681ae63Sjeremylt /**
1161a681ae63Sjeremylt   @brief Get the size of blocks in the CeedElemRestriction
1162a681ae63Sjeremylt 
1163ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction
1164d1d35e2fSjeremylt   @param[out] blk_size Variable to store size of blocks
1165a681ae63Sjeremylt 
1166a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1167a681ae63Sjeremylt 
1168b7c9bbdaSJeremy L Thompson   @ref Advanced
1169a681ae63Sjeremylt **/
11702b730f8bSJeremy L Thompson int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, CeedInt *blk_size) {
1171d1d35e2fSjeremylt   *blk_size = rstr->blk_size;
1172e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1173a681ae63Sjeremylt }
1174a681ae63Sjeremylt 
1175a681ae63Sjeremylt /**
1176d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
11771469ee4dSjeremylt 
1178ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
1179d1d35e2fSjeremylt   @param[out] mult Vector to store multiplicity (of size l_size)
11801469ee4dSjeremylt 
11811469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
11821469ee4dSjeremylt 
11837a982d89SJeremy L. Thompson   @ref User
11841469ee4dSjeremylt **/
11852b730f8bSJeremy L Thompson int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, CeedVector mult) {
1186d1d35e2fSjeremylt   CeedVector e_vec;
11871469ee4dSjeremylt 
118825509ebbSRezgar Shakeri   // Create e_vec to hold intermediate computation in E^T (E 1)
11892b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionCreateVector(rstr, NULL, &e_vec));
11901469ee4dSjeremylt 
119125509ebbSRezgar Shakeri   // Compute e_vec = E * 1
11922b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 1.0));
11932b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, CEED_REQUEST_IMMEDIATE));
119425509ebbSRezgar Shakeri   // Compute multiplicity, mult = E^T * e_vec = E^T (E 1)
11952b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 0.0));
11962b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, CEED_REQUEST_IMMEDIATE));
11971469ee4dSjeremylt   // Cleanup
11982b730f8bSJeremy L Thompson   CeedCall(CeedVectorDestroy(&e_vec));
1199e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
12001469ee4dSjeremylt }
12011469ee4dSjeremylt 
12021469ee4dSjeremylt /**
1203f02ca4a2SJed Brown   @brief View a CeedElemRestriction
1204f02ca4a2SJed Brown 
1205f02ca4a2SJed Brown   @param[in] rstr   CeedElemRestriction to view
1206f02ca4a2SJed Brown   @param[in] stream Stream to write; typically stdout/stderr or a file
1207f02ca4a2SJed Brown 
1208f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
1209f02ca4a2SJed Brown 
12107a982d89SJeremy L. Thompson   @ref User
1211f02ca4a2SJed Brown **/
1212f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
12137509a596Sjeremylt   char stridesstr[500];
12142b730f8bSJeremy L Thompson   if (rstr->strides) {
12152b730f8bSJeremy L Thompson     sprintf(stridesstr, "[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "]", rstr->strides[0], rstr->strides[1], rstr->strides[2]);
12162b730f8bSJeremy L Thompson   } else {
1217990fdeb6SJeremy L Thompson     sprintf(stridesstr, "%" CeedInt_FMT, rstr->comp_stride);
12182b730f8bSJeremy L Thompson   }
12197509a596Sjeremylt 
12202b730f8bSJeremy L Thompson   fprintf(stream, "%sCeedElemRestriction from (%td, %" CeedInt_FMT ") to %" CeedInt_FMT " elements with %" CeedInt_FMT " nodes each and %s %s\n",
12212b730f8bSJeremy L Thompson           rstr->blk_size > 1 ? "Blocked " : "", rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
1222d979a051Sjeremylt           rstr->strides ? "strides" : "component stride", stridesstr);
1223e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1224f02ca4a2SJed Brown }
1225f02ca4a2SJed Brown 
1226f02ca4a2SJed Brown /**
1227b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
1228b11c1e72Sjeremylt 
1229ea61e9acSJeremy L Thompson   @param[in,out] rstr CeedElemRestriction to destroy
1230b11c1e72Sjeremylt 
1231b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1232dfdf5a53Sjeremylt 
12337a982d89SJeremy L. Thompson   @ref User
1234b11c1e72Sjeremylt **/
12354ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
1236393ac2cdSJeremy L Thompson   if (!*rstr || *rstr == CEED_ELEMRESTRICTION_NONE || --(*rstr)->ref_count > 0) {
1237ad6481ceSJeremy L Thompson     *rstr = NULL;
1238ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
1239ad6481ceSJeremy L Thompson   }
12406574a04fSJeremy L Thompson   CeedCheck((*rstr)->num_readers == 0, (*rstr)->ceed, CEED_ERROR_ACCESS,
12416574a04fSJeremy L Thompson             "Cannot destroy CeedElemRestriction, a process has read access to the offset data");
1242c17ec2beSJeremy L Thompson 
1243c17ec2beSJeremy L Thompson   // Only destroy backend data once between rstr and unsigned copy
1244c17ec2beSJeremy L Thompson   if ((*rstr)->rstr_signed) CeedCall(CeedElemRestrictionDestroy(&(*rstr)->rstr_signed));
1245c17ec2beSJeremy L Thompson   else if ((*rstr)->Destroy) CeedCall((*rstr)->Destroy(*rstr));
1246c17ec2beSJeremy L Thompson 
12472b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*rstr)->strides));
12482b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*rstr)->ceed));
12492b730f8bSJeremy L Thompson   CeedCall(CeedFree(rstr));
1250e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1251d7b241e6Sjeremylt }
1252d7b241e6Sjeremylt 
1253d7b241e6Sjeremylt /// @}
1254