xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-elemrestriction.c (revision e7f679fc6de93686a880ec2b7b7a43611d8847a6)
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*e7f679fcSJeremy L Thompson   @param[out] block_offsets  Array of permuted and padded array values of shape [@a num_block, @a elem_size, @a block_size].
29*e7f679fcSJeremy L Thompson   @param[in]  num_block      Number of blocks
30ea61e9acSJeremy L Thompson   @param[in]  num_elem       Number of elements
31*e7f679fcSJeremy L Thompson   @param[in]  block_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 **/
38*e7f679fcSJeremy L Thompson int CeedPermutePadOffsets(const CeedInt *offsets, CeedInt *block_offsets, CeedInt num_block, CeedInt num_elem, CeedInt block_size,
39*e7f679fcSJeremy L Thompson                           CeedInt elem_size) {
40*e7f679fcSJeremy L Thompson   for (CeedInt e = 0; e < num_block * block_size; e += block_size) {
41*e7f679fcSJeremy L Thompson     for (CeedInt j = 0; j < block_size; j++) {
422b730f8bSJeremy L Thompson       for (CeedInt k = 0; k < elem_size; k++) {
43*e7f679fcSJeremy L Thompson         block_offsets[e * elem_size + k * block_size + j] = offsets[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
442b730f8bSJeremy L Thompson       }
452b730f8bSJeremy L Thompson     }
462b730f8bSJeremy L Thompson   }
47e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
487a982d89SJeremy L. Thompson }
497a982d89SJeremy L. Thompson 
5077d1c127SSebastian Grimberg /**
5177d1c127SSebastian Grimberg   @brief Permute and pad orientations for a blocked restriction
5277d1c127SSebastian Grimberg 
53fcbe8c06SSebastian Grimberg   @param[in]  orients       Array of shape [@a num_elem, @a elem_size].
54*e7f679fcSJeremy L Thompson   @param[out] block_orients Array of permuted and padded array values of shape [@a num_block, @a elem_size, @a block_size].
55*e7f679fcSJeremy L Thompson   @param[in]  num_block     Number of blocks
5677d1c127SSebastian Grimberg   @param[in]  num_elem      Number of elements
57*e7f679fcSJeremy L Thompson   @param[in]  block_size    Number of elements in a block
5877d1c127SSebastian Grimberg   @param[in]  elem_size     Size of each element
5977d1c127SSebastian Grimberg 
6077d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
6177d1c127SSebastian Grimberg 
6277d1c127SSebastian Grimberg   @ref Utility
6377d1c127SSebastian Grimberg **/
64*e7f679fcSJeremy L Thompson int CeedPermutePadOrients(const bool *orients, bool *block_orients, CeedInt num_block, CeedInt num_elem, CeedInt block_size, CeedInt elem_size) {
65*e7f679fcSJeremy L Thompson   for (CeedInt e = 0; e < num_block * block_size; e += block_size) {
66*e7f679fcSJeremy L Thompson     for (CeedInt j = 0; j < block_size; j++) {
6777d1c127SSebastian Grimberg       for (CeedInt k = 0; k < elem_size; k++) {
68*e7f679fcSJeremy L Thompson         block_orients[e * elem_size + k * block_size + j] = orients[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
6977d1c127SSebastian Grimberg       }
7077d1c127SSebastian Grimberg     }
7177d1c127SSebastian Grimberg   }
7277d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
7377d1c127SSebastian Grimberg }
7477d1c127SSebastian Grimberg 
750c73c039SSebastian Grimberg /**
760c73c039SSebastian Grimberg   @brief Permute and pad curl-conforming orientations for a blocked restriction
770c73c039SSebastian Grimberg 
780c73c039SSebastian Grimberg   @param[in]  curl_orients       Array of shape [@a num_elem, @a 3 * elem_size].
79*e7f679fcSJeremy L Thompson   @param[out] block_curl_orients Array of permuted and padded array values of shape [@a num_block, @a elem_size, @a block_size].
80*e7f679fcSJeremy L Thompson   @param[in]  num_block          Number of blocks
810c73c039SSebastian Grimberg   @param[in]  num_elem           Number of elements
82*e7f679fcSJeremy L Thompson   @param[in]  block_size         Number of elements in a block
830c73c039SSebastian Grimberg   @param[in]  elem_size          Size of each element
840c73c039SSebastian Grimberg 
850c73c039SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
860c73c039SSebastian Grimberg 
870c73c039SSebastian Grimberg   @ref Utility
880c73c039SSebastian Grimberg **/
89*e7f679fcSJeremy L Thompson int CeedPermutePadCurlOrients(const CeedInt8 *curl_orients, CeedInt8 *block_curl_orients, CeedInt num_block, CeedInt num_elem, CeedInt block_size,
900c73c039SSebastian Grimberg                               CeedInt elem_size) {
91*e7f679fcSJeremy L Thompson   for (CeedInt e = 0; e < num_block * block_size; e += block_size) {
92*e7f679fcSJeremy L Thompson     for (CeedInt j = 0; j < block_size; j++) {
930c73c039SSebastian Grimberg       for (CeedInt k = 0; k < elem_size; k++) {
94*e7f679fcSJeremy L Thompson         block_curl_orients[e * elem_size + k * block_size + j] = curl_orients[CeedIntMin(e + j, num_elem - 1) * elem_size + k];
950c73c039SSebastian Grimberg       }
960c73c039SSebastian Grimberg     }
970c73c039SSebastian Grimberg   }
980c73c039SSebastian Grimberg   return CEED_ERROR_SUCCESS;
990c73c039SSebastian Grimberg }
1000c73c039SSebastian Grimberg 
1017a982d89SJeremy L. Thompson /// @}
1027a982d89SJeremy L. Thompson 
1037a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1047a982d89SJeremy L. Thompson /// CeedElemRestriction Backend API
1057a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1067a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionBackend
1077a982d89SJeremy L. Thompson /// @{
1087a982d89SJeremy L. Thompson 
1097a982d89SJeremy L. Thompson /**
110fcbe8c06SSebastian Grimberg   @brief Get the type of a CeedElemRestriction
111a681ae63Sjeremylt 
112fcbe8c06SSebastian Grimberg   @param[in]  rstr      CeedElemRestriction
113fcbe8c06SSebastian Grimberg   @param[out] rstr_type Variable to store restriction type
114fcbe8c06SSebastian Grimberg 
115fcbe8c06SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
116fcbe8c06SSebastian Grimberg 
117fcbe8c06SSebastian Grimberg   @ref Backend
118fcbe8c06SSebastian Grimberg **/
119fcbe8c06SSebastian Grimberg int CeedElemRestrictionGetType(CeedElemRestriction rstr, CeedRestrictionType *rstr_type) {
120fcbe8c06SSebastian Grimberg   *rstr_type = rstr->rstr_type;
121fcbe8c06SSebastian Grimberg   return CEED_ERROR_SUCCESS;
122fcbe8c06SSebastian Grimberg }
123fcbe8c06SSebastian Grimberg 
124fcbe8c06SSebastian Grimberg /**
125fcbe8c06SSebastian Grimberg   @brief Get the strided status of a CeedElemRestriction
126fcbe8c06SSebastian Grimberg 
127fcbe8c06SSebastian Grimberg   @param[in]  rstr       CeedElemRestriction
128fcbe8c06SSebastian Grimberg   @param[out] is_strided Variable to store strided status, 1 if strided else 0
129fcbe8c06SSebastian Grimberg **/
130fcbe8c06SSebastian Grimberg int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) {
131fcbe8c06SSebastian Grimberg   *is_strided = (rstr->rstr_type == CEED_RESTRICTION_STRIDED);
132fcbe8c06SSebastian Grimberg   return CEED_ERROR_SUCCESS;
133fcbe8c06SSebastian Grimberg }
134fcbe8c06SSebastian Grimberg 
135fcbe8c06SSebastian Grimberg /**
136a681ae63Sjeremylt   @brief Get the strides of a strided CeedElemRestriction
1377a982d89SJeremy L. Thompson 
138ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
139a681ae63Sjeremylt   @param[out] strides Variable to store strides array
1407a982d89SJeremy L. Thompson 
1417a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1427a982d89SJeremy L. Thompson 
1437a982d89SJeremy L. Thompson   @ref Backend
1447a982d89SJeremy L. Thompson **/
1452b730f8bSJeremy L Thompson int CeedElemRestrictionGetStrides(CeedElemRestriction rstr, CeedInt (*strides)[3]) {
1466574a04fSJeremy L Thompson   CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
1472b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*strides)[i] = rstr->strides[i];
148e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1497a982d89SJeremy L. Thompson }
1507a982d89SJeremy L. Thompson 
1517a982d89SJeremy L. Thompson /**
15277d1c127SSebastian Grimberg   @brief Get the backend stride status of a CeedElemRestriction
15377d1c127SSebastian Grimberg 
15477d1c127SSebastian Grimberg   @param[in]  rstr                 CeedElemRestriction
15577d1c127SSebastian Grimberg   @param[out] has_backend_strides  Variable to store stride status
15677d1c127SSebastian Grimberg 
15777d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
15877d1c127SSebastian Grimberg 
15977d1c127SSebastian Grimberg   @ref Backend
16077d1c127SSebastian Grimberg **/
16177d1c127SSebastian Grimberg int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, bool *has_backend_strides) {
16277d1c127SSebastian Grimberg   CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no stride data");
16377d1c127SSebastian Grimberg   *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) &&
16477d1c127SSebastian Grimberg                           (rstr->strides[2] == CEED_STRIDES_BACKEND[2]));
16577d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
16677d1c127SSebastian Grimberg }
16777d1c127SSebastian Grimberg 
16877d1c127SSebastian Grimberg /**
169bd33150aSjeremylt   @brief Get read-only access to a CeedElemRestriction offsets array by memtype
170bd33150aSjeremylt 
171ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction to retrieve offsets
172fcbe8c06SSebastian Grimberg   @param[in]  mem_type Memory type on which to access the array.
173fcbe8c06SSebastian Grimberg                          If the backend uses a different memory type, this will perform a copy (possibly cached).
174d1d35e2fSjeremylt   @param[out] offsets  Array on memory type mem_type
175bd33150aSjeremylt 
176bd33150aSjeremylt   @return An error code: 0 - success, otherwise - failure
177bd33150aSjeremylt 
178bd33150aSjeremylt   @ref User
179bd33150aSjeremylt **/
1802b730f8bSJeremy L Thompson int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) {
1817c1dbaffSSebastian Grimberg   if (rstr->rstr_base) {
1827c1dbaffSSebastian Grimberg     CeedCall(CeedElemRestrictionGetOffsets(rstr->rstr_base, mem_type, offsets));
183c17ec2beSJeremy L Thompson   } else {
1846574a04fSJeremy L Thompson     CeedCheck(rstr->GetOffsets, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetOffsets");
1852b730f8bSJeremy L Thompson     CeedCall(rstr->GetOffsets(rstr, mem_type, offsets));
186d1d35e2fSjeremylt     rstr->num_readers++;
187c17ec2beSJeremy L Thompson   }
188e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
189430758c8SJeremy L Thompson }
190430758c8SJeremy L Thompson 
191430758c8SJeremy L Thompson /**
192430758c8SJeremy L Thompson   @brief Restore an offsets array obtained using CeedElemRestrictionGetOffsets()
193430758c8SJeremy L Thompson 
194ea61e9acSJeremy L Thompson   @param[in] rstr    CeedElemRestriction to restore
195ea61e9acSJeremy L Thompson   @param[in] offsets Array of offset data
196430758c8SJeremy L Thompson 
197430758c8SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
198430758c8SJeremy L Thompson 
199430758c8SJeremy L Thompson   @ref User
200430758c8SJeremy L Thompson **/
2012b730f8bSJeremy L Thompson int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr, const CeedInt **offsets) {
2027c1dbaffSSebastian Grimberg   if (rstr->rstr_base) {
2037c1dbaffSSebastian Grimberg     CeedCall(CeedElemRestrictionRestoreOffsets(rstr->rstr_base, offsets));
204c17ec2beSJeremy L Thompson   } else {
205430758c8SJeremy L Thompson     *offsets = NULL;
206d1d35e2fSjeremylt     rstr->num_readers--;
207c17ec2beSJeremy L Thompson   }
208e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
209bd33150aSjeremylt }
210bd33150aSjeremylt 
211bd33150aSjeremylt /**
21277d1c127SSebastian Grimberg   @brief Get read-only access to a CeedElemRestriction orientations array by memtype
2133ac43b2cSJeremy L Thompson 
21477d1c127SSebastian Grimberg   @param[in]  rstr     CeedElemRestriction to retrieve orientations
215fcbe8c06SSebastian Grimberg   @param[in]  mem_type Memory type on which to access the array.
216fcbe8c06SSebastian Grimberg                          If the backend uses a different memory type, this will perform a copy (possibly cached).
21777d1c127SSebastian Grimberg   @param[out] orients  Array on memory type mem_type
2183ac43b2cSJeremy L Thompson 
2193ac43b2cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2203ac43b2cSJeremy L Thompson 
22177d1c127SSebastian Grimberg   @ref User
2223ac43b2cSJeremy L Thompson **/
22377d1c127SSebastian Grimberg int CeedElemRestrictionGetOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const bool **orients) {
224fcbe8c06SSebastian Grimberg   CeedCheck(rstr->GetOrientations, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetOrientations");
22577d1c127SSebastian Grimberg   CeedCall(rstr->GetOrientations(rstr, mem_type, orients));
22677d1c127SSebastian Grimberg   rstr->num_readers++;
227e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2283ac43b2cSJeremy L Thompson }
2293ac43b2cSJeremy L Thompson 
2303ac43b2cSJeremy L Thompson /**
23177d1c127SSebastian Grimberg   @brief Restore an orientations array obtained using CeedElemRestrictionGetOrientations()
232b435c5a6Srezgarshakeri 
23377d1c127SSebastian Grimberg   @param[in] rstr    CeedElemRestriction to restore
23477d1c127SSebastian Grimberg   @param[in] orients Array of orientation data
235b435c5a6Srezgarshakeri 
236b435c5a6Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
237b435c5a6Srezgarshakeri 
23877d1c127SSebastian Grimberg   @ref User
239b435c5a6Srezgarshakeri **/
24077d1c127SSebastian Grimberg int CeedElemRestrictionRestoreOrientations(CeedElemRestriction rstr, const bool **orients) {
24177d1c127SSebastian Grimberg   *orients = NULL;
24277d1c127SSebastian Grimberg   rstr->num_readers--;
243b435c5a6Srezgarshakeri   return CEED_ERROR_SUCCESS;
244b435c5a6Srezgarshakeri }
245b435c5a6Srezgarshakeri 
246b435c5a6Srezgarshakeri /**
24777d1c127SSebastian Grimberg   @brief Get read-only access to a CeedElemRestriction curl-conforming orientations array by memtype
2487a982d89SJeremy L. Thompson 
24977d1c127SSebastian Grimberg   @param[in]  rstr         CeedElemRestriction to retrieve curl-conforming 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] curl_orients Array on memory type mem_type
2537a982d89SJeremy L. Thompson 
2547a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2557a982d89SJeremy L. Thompson 
25677d1c127SSebastian Grimberg   @ref User
2577a982d89SJeremy L. Thompson **/
2580c73c039SSebastian Grimberg int CeedElemRestrictionGetCurlOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt8 **curl_orients) {
259fcbe8c06SSebastian Grimberg   CeedCheck(rstr->GetCurlOrientations, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetCurlOrientations");
26077d1c127SSebastian Grimberg   CeedCall(rstr->GetCurlOrientations(rstr, mem_type, curl_orients));
26177d1c127SSebastian Grimberg   rstr->num_readers++;
26277d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
26377d1c127SSebastian Grimberg }
26477d1c127SSebastian Grimberg 
26577d1c127SSebastian Grimberg /**
26677d1c127SSebastian Grimberg   @brief Restore an orientations array obtained using CeedElemRestrictionGetCurlOrientations()
26777d1c127SSebastian Grimberg 
26877d1c127SSebastian Grimberg   @param[in] rstr         CeedElemRestriction to restore
26977d1c127SSebastian Grimberg   @param[in] curl_orients Array of orientation data
27077d1c127SSebastian Grimberg 
27177d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
27277d1c127SSebastian Grimberg 
27377d1c127SSebastian Grimberg   @ref User
27477d1c127SSebastian Grimberg **/
2750c73c039SSebastian Grimberg int CeedElemRestrictionRestoreCurlOrientations(CeedElemRestriction rstr, const CeedInt8 **curl_orients) {
27677d1c127SSebastian Grimberg   *curl_orients = NULL;
27777d1c127SSebastian Grimberg   rstr->num_readers--;
278e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2797a982d89SJeremy L. Thompson }
2807a982d89SJeremy L. Thompson 
2817a982d89SJeremy L. Thompson /**
28249fd234cSJeremy L Thompson 
28349fd234cSJeremy L Thompson   @brief Get the E-vector layout of a CeedElemRestriction
28449fd234cSJeremy L Thompson 
285ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
286fcbe8c06SSebastian Grimberg   @param[out] layout  Variable to store layout array, stored as [nodes, components, elements].
287fcbe8c06SSebastian 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]
28849fd234cSJeremy L Thompson 
28949fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
29049fd234cSJeremy L Thompson 
29149fd234cSJeremy L Thompson   @ref Backend
29249fd234cSJeremy L Thompson **/
2932b730f8bSJeremy L Thompson int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, CeedInt (*layout)[3]) {
2946574a04fSJeremy L Thompson   CeedCheck(rstr->layout[0], rstr->ceed, CEED_ERROR_MINOR, "ElemRestriction has no layout data");
2952b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*layout)[i] = rstr->layout[i];
296e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
29749fd234cSJeremy L Thompson }
29849fd234cSJeremy L Thompson 
29949fd234cSJeremy L Thompson /**
30049fd234cSJeremy L Thompson 
30149fd234cSJeremy L Thompson   @brief Set the E-vector layout of a CeedElemRestriction
30249fd234cSJeremy L Thompson 
303ea61e9acSJeremy L Thompson   @param[in] rstr   CeedElemRestriction
304ea61e9acSJeremy L Thompson   @param[in] layout Variable to containing layout array, stored as [nodes, components, elements].
305ea61e9acSJeremy 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]
30649fd234cSJeremy L Thompson 
30749fd234cSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
30849fd234cSJeremy L Thompson 
30949fd234cSJeremy L Thompson   @ref Backend
31049fd234cSJeremy L Thompson **/
3112b730f8bSJeremy L Thompson int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, CeedInt layout[3]) {
3122b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) rstr->layout[i] = layout[i];
313e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
31449fd234cSJeremy L Thompson }
31549fd234cSJeremy L Thompson 
31649fd234cSJeremy L Thompson /**
3177a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedElemRestriction
3187a982d89SJeremy L. Thompson 
319ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
3207a982d89SJeremy L. Thompson   @param[out] data Variable to store data
3217a982d89SJeremy L. Thompson 
3227a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3237a982d89SJeremy L. Thompson 
3247a982d89SJeremy L. Thompson   @ref Backend
3257a982d89SJeremy L. Thompson **/
326777ff853SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) {
327777ff853SJeremy L Thompson   *(void **)data = rstr->data;
328e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3297a982d89SJeremy L. Thompson }
3307a982d89SJeremy L. Thompson 
3317a982d89SJeremy L. Thompson /**
3327a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedElemRestriction
3337a982d89SJeremy L. Thompson 
334ea61e9acSJeremy L Thompson   @param[in,out] rstr CeedElemRestriction
335ea61e9acSJeremy L Thompson   @param[in]     data Data to set
3367a982d89SJeremy L. Thompson 
3377a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3387a982d89SJeremy L. Thompson 
3397a982d89SJeremy L. Thompson   @ref Backend
3407a982d89SJeremy L. Thompson **/
341777ff853SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) {
342777ff853SJeremy L Thompson   rstr->data = data;
343e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3447a982d89SJeremy L. Thompson }
3457a982d89SJeremy L. Thompson 
34634359f16Sjeremylt /**
34734359f16Sjeremylt   @brief Increment the reference counter for a CeedElemRestriction
34834359f16Sjeremylt 
349ea61e9acSJeremy L Thompson   @param[in,out] rstr ElemRestriction to increment the reference counter
35034359f16Sjeremylt 
35134359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
35234359f16Sjeremylt 
35334359f16Sjeremylt   @ref Backend
35434359f16Sjeremylt **/
3559560d06aSjeremylt int CeedElemRestrictionReference(CeedElemRestriction rstr) {
35634359f16Sjeremylt   rstr->ref_count++;
35734359f16Sjeremylt   return CEED_ERROR_SUCCESS;
35834359f16Sjeremylt }
35934359f16Sjeremylt 
3606e15d496SJeremy L Thompson /**
3616e15d496SJeremy L Thompson   @brief Estimate number of FLOPs required to apply CeedElemRestriction in t_mode
3626e15d496SJeremy L Thompson 
363ea61e9acSJeremy L Thompson   @param[in]  rstr   ElemRestriction to estimate FLOPs for
364ea61e9acSJeremy L Thompson   @param[in]  t_mode Apply restriction or transpose
365ea61e9acSJeremy L Thompson   @param[out] flops  Address of variable to hold FLOPs estimate
3666e15d496SJeremy L Thompson 
3676e15d496SJeremy L Thompson   @ref Backend
3686e15d496SJeremy L Thompson **/
3692b730f8bSJeremy L Thompson int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedSize *flops) {
370*e7f679fcSJeremy L Thompson   CeedInt             e_size = rstr->num_block * rstr->block_size * rstr->elem_size * rstr->num_comp, scale = 0;
37189edb9e3SSebastian Grimberg   CeedRestrictionType rstr_type;
37289edb9e3SSebastian Grimberg   CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type));
37377d1c127SSebastian Grimberg   if (t_mode == CEED_TRANSPOSE) {
37489edb9e3SSebastian Grimberg     switch (rstr_type) {
37589edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STRIDED:
37689edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STANDARD:
37777d1c127SSebastian Grimberg         scale = 1;
37889edb9e3SSebastian Grimberg         break;
37989edb9e3SSebastian Grimberg       case CEED_RESTRICTION_ORIENTED:
38077d1c127SSebastian Grimberg         scale = 2;
38189edb9e3SSebastian Grimberg         break;
38289edb9e3SSebastian Grimberg       case CEED_RESTRICTION_CURL_ORIENTED:
38377d1c127SSebastian Grimberg         scale = 6;
38489edb9e3SSebastian Grimberg         break;
3856e15d496SJeremy L Thompson     }
38677d1c127SSebastian Grimberg   } else {
38789edb9e3SSebastian Grimberg     switch (rstr_type) {
38889edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STRIDED:
38989edb9e3SSebastian Grimberg       case CEED_RESTRICTION_STANDARD:
39077d1c127SSebastian Grimberg         scale = 0;
39189edb9e3SSebastian Grimberg         break;
39289edb9e3SSebastian Grimberg       case CEED_RESTRICTION_ORIENTED:
39377d1c127SSebastian Grimberg         scale = 1;
39489edb9e3SSebastian Grimberg         break;
39589edb9e3SSebastian Grimberg       case CEED_RESTRICTION_CURL_ORIENTED:
39677d1c127SSebastian Grimberg         scale = 5;
39789edb9e3SSebastian Grimberg         break;
39877d1c127SSebastian Grimberg     }
39977d1c127SSebastian Grimberg   }
4006e15d496SJeremy L Thompson   *flops = e_size * scale;
4016e15d496SJeremy L Thompson 
4026e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4036e15d496SJeremy L Thompson }
4046e15d496SJeremy L Thompson 
4057a982d89SJeremy L. Thompson /// @}
4067a982d89SJeremy L. Thompson 
40715910d16Sjeremylt /// @cond DOXYGEN_SKIP
40815910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none;
40915910d16Sjeremylt /// @endcond
41015910d16Sjeremylt 
4117a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
4127a982d89SJeremy L. Thompson /// CeedElemRestriction Public API
4137a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
4147a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser
415d7b241e6Sjeremylt /// @{
416d7b241e6Sjeremylt 
4177a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend
41845f1e315Sjeremylt const CeedInt CEED_STRIDES_BACKEND[3] = {0};
4197a982d89SJeremy L. Thompson 
4204cc79fe7SJed Brown /// Indicate that no CeedElemRestriction is provided by the user
4212b730f8bSJeremy L Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = &ceed_elemrestriction_none;
4227a982d89SJeremy L. Thompson 
423d7b241e6Sjeremylt /**
424b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
425d7b241e6Sjeremylt 
426ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
427ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array
428ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
429ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
430fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
431fcbe8c06SSebastian 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.
432fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
433fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
434ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
435ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
436fcbe8c06SSebastian Grimberg   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
437fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
438fcbe8c06SSebastian Grimberg 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
439ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
440d7b241e6Sjeremylt 
441b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
442dfdf5a53Sjeremylt 
4437a982d89SJeremy L. Thompson   @ref User
444b11c1e72Sjeremylt **/
4452b730f8bSJeremy L Thompson int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
4462b730f8bSJeremy L Thompson                               CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) {
4475fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
4485fe0d4faSjeremylt     Ceed delegate;
4496574a04fSJeremy L Thompson 
4502b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
45177d1c127SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
4522b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr));
453e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
4545fe0d4faSjeremylt   }
4555fe0d4faSjeremylt 
456*e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
4576574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
4586574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
4596574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
460e022e1f8SJeremy L Thompson 
4612b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
462db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
463d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
464d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
465d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
466d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
467d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
468d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
469*e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
470*e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
47161a27d74SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_STANDARD;
472fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, NULL, *rstr));
473e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
474d7b241e6Sjeremylt }
475d7b241e6Sjeremylt 
476d7b241e6Sjeremylt /**
47777d1c127SSebastian Grimberg   @brief Create a CeedElemRestriction with orientation signs
478fc0567d9Srezgarshakeri 
479ea61e9acSJeremy L Thompson   @param[in]  ceed        Ceed object where the CeedElemRestriction will be created
480ea61e9acSJeremy L Thompson   @param[in]  num_elem    Number of elements described in the @a offsets array
481ea61e9acSJeremy L Thompson   @param[in]  elem_size   Size (number of "nodes") per element
482ea61e9acSJeremy L Thompson   @param[in]  num_comp    Number of field components per interpolation node (1 for scalar fields)
483fcbe8c06SSebastian Grimberg   @param[in]  comp_stride Stride between components for the same L-vector "node".
484fcbe8c06SSebastian 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.
485fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
486fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
487ea61e9acSJeremy L Thompson   @param[in]  mem_type    Memory type of the @a offsets array, see CeedMemType
488ea61e9acSJeremy L Thompson   @param[in]  copy_mode   Copy mode for the @a offsets array, see CeedCopyMode
489fcbe8c06SSebastian Grimberg   @param[in]  offsets     Array of shape [@a num_elem, @a elem_size].
490fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
491fcbe8c06SSebastian Grimberg 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
49277d1c127SSebastian 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.
493ea61e9acSJeremy L Thompson   @param[out] rstr        Address of the variable where the newly created CeedElemRestriction will be stored
494fc0567d9Srezgarshakeri 
495fc0567d9Srezgarshakeri   @return An error code: 0 - success, otherwise - failure
496fc0567d9Srezgarshakeri 
497fc0567d9Srezgarshakeri   @ref User
498fc0567d9Srezgarshakeri **/
4992b730f8bSJeremy L Thompson int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
50077d1c127SSebastian Grimberg                                       CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orients,
501fc0567d9Srezgarshakeri                                       CeedElemRestriction *rstr) {
502fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreate) {
503fc0567d9Srezgarshakeri     Ceed delegate;
5046574a04fSJeremy L Thompson 
5052b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
506fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
5072b730f8bSJeremy L Thompson     CeedCall(
50877d1c127SSebastian Grimberg         CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, orients, rstr));
509fc0567d9Srezgarshakeri     return CEED_ERROR_SUCCESS;
510fc0567d9Srezgarshakeri   }
511fc0567d9Srezgarshakeri 
512*e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
5136574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
5146574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
5156574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
516e022e1f8SJeremy L Thompson 
5172b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
518db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
519fc0567d9Srezgarshakeri   (*rstr)->ref_count   = 1;
520fc0567d9Srezgarshakeri   (*rstr)->num_elem    = num_elem;
521fc0567d9Srezgarshakeri   (*rstr)->elem_size   = elem_size;
522fc0567d9Srezgarshakeri   (*rstr)->num_comp    = num_comp;
523fc0567d9Srezgarshakeri   (*rstr)->comp_stride = comp_stride;
524fc0567d9Srezgarshakeri   (*rstr)->l_size      = l_size;
525*e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
526*e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
527fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_ORIENTED;
528fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, orients, NULL, *rstr));
52977d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
53077d1c127SSebastian Grimberg }
53177d1c127SSebastian Grimberg 
53277d1c127SSebastian Grimberg /**
53377d1c127SSebastian Grimberg   @brief Create a CeedElemRestriction with a general tridiagonal transformation matrix for curl-conforming elements
53477d1c127SSebastian Grimberg 
53577d1c127SSebastian Grimberg   @param[in]  ceed         Ceed object where the CeedElemRestriction will be created
53677d1c127SSebastian Grimberg   @param[in]  num_elem     Number of elements described in the @a offsets array
53777d1c127SSebastian Grimberg   @param[in]  elem_size    Size (number of "nodes") per element
53877d1c127SSebastian Grimberg   @param[in]  num_comp     Number of field components per interpolation node (1 for scalar fields)
539fcbe8c06SSebastian Grimberg   @param[in]  comp_stride  Stride between components for the same L-vector "node".
540fcbe8c06SSebastian 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.
541fcbe8c06SSebastian Grimberg   @param[in]  l_size       The size of the L-vector.
542fcbe8c06SSebastian Grimberg                              This vector may be larger than the elements and fields given by this restriction.
54377d1c127SSebastian Grimberg   @param[in]  mem_type     Memory type of the @a offsets array, see CeedMemType
54477d1c127SSebastian Grimberg   @param[in]  copy_mode    Copy mode for the @a offsets array, see CeedCopyMode
545fcbe8c06SSebastian Grimberg   @param[in]  offsets      Array of shape [@a num_elem, @a elem_size].
546fcbe8c06SSebastian Grimberg                              Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i,
547fcbe8c06SSebastian Grimberg where 0 <= i < @a num_elem. All offsets must be in the range [0, @a l_size - 1].
5487c1dbaffSSebastian Grimberg   @param[in]  curl_orients Array of shape [@a num_elem, @a 3 * elem_size] representing a row-major tridiagonal matrix (curl_orients[i * 3 * elem_size]
5497c1dbaffSSebastian 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
5507c1dbaffSSebastian Grimberg orientation matrix allows for pairs of face degrees of freedom on elements for H(curl) spaces to be coupled in the element restriction operation,
5517c1dbaffSSebastian Grimberg which is a way to resolve face orientation issues for 3D meshes (https://dl.acm.org/doi/pdf/10.1145/3524456).
55277d1c127SSebastian Grimberg   @param[out] rstr         Address of the variable where the newly created CeedElemRestriction will be stored
55377d1c127SSebastian Grimberg 
55477d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
55577d1c127SSebastian Grimberg 
55677d1c127SSebastian Grimberg   @ref User
55777d1c127SSebastian Grimberg **/
55877d1c127SSebastian Grimberg int CeedElemRestrictionCreateCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size,
5590c73c039SSebastian Grimberg                                           CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const CeedInt8 *curl_orients,
56077d1c127SSebastian Grimberg                                           CeedElemRestriction *rstr) {
561fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreate) {
56277d1c127SSebastian Grimberg     Ceed delegate;
56377d1c127SSebastian Grimberg 
56477d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
565fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
56677d1c127SSebastian Grimberg     CeedCall(CeedElemRestrictionCreateCurlOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
56777d1c127SSebastian Grimberg                                                    curl_orients, rstr));
56877d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
56977d1c127SSebastian Grimberg   }
57077d1c127SSebastian Grimberg 
571*e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
57277d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
57377d1c127SSebastian Grimberg   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
57477d1c127SSebastian Grimberg   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
57577d1c127SSebastian Grimberg 
57677d1c127SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
577fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
57877d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
57977d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
58077d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
58177d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
58277d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
58377d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
584*e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_elem;
585*e7f679fcSJeremy L Thompson   (*rstr)->block_size  = 1;
586fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_CURL_ORIENTED;
587fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, curl_orients, *rstr));
588fc0567d9Srezgarshakeri   return CEED_ERROR_SUCCESS;
589fc0567d9Srezgarshakeri }
590fc0567d9Srezgarshakeri 
591fc0567d9Srezgarshakeri /**
5927509a596Sjeremylt   @brief Create a strided CeedElemRestriction
593d7b241e6Sjeremylt 
594ea61e9acSJeremy L Thompson   @param[in]  ceed      Ceed object where the CeedElemRestriction will be created
595ea61e9acSJeremy L Thompson   @param[in]  num_elem  Number of elements described by the restriction
596ea61e9acSJeremy L Thompson   @param[in]  elem_size Size (number of "nodes") per element
597ea61e9acSJeremy L Thompson   @param[in]  num_comp  Number of field components per interpolation "node" (1 for scalar fields)
598fcbe8c06SSebastian Grimberg   @param[in]  l_size    The size of the L-vector.
599fcbe8c06SSebastian Grimberg                           This vector may be larger than the elements and fields given by this restriction.
600fcbe8c06SSebastian Grimberg   @param[in]  strides   Array for strides between [nodes, components, elements].
601fcbe8c06SSebastian 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].
602fcbe8c06SSebastian Grimberg                           @a CEED_STRIDES_BACKEND may be used with vectors created by a Ceed backend.
603ea61e9acSJeremy L Thompson   @param[out] rstr      Address of the variable where the newly created CeedElemRestriction will be stored
604d7b241e6Sjeremylt 
605b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
606dfdf5a53Sjeremylt 
6077a982d89SJeremy L. Thompson   @ref User
608b11c1e72Sjeremylt **/
6092b730f8bSJeremy L Thompson int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedSize l_size, const CeedInt strides[3],
610f90c8643Sjeremylt                                      CeedElemRestriction *rstr) {
6115fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreate) {
6125fe0d4faSjeremylt     Ceed delegate;
613b04eb3d9SSebastian Grimberg 
6142b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
615fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreate");
6162b730f8bSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, l_size, strides, rstr));
617e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6185fe0d4faSjeremylt   }
6195fe0d4faSjeremylt 
620*e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
6216574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
6226574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
623*e7f679fcSJeremy L Thompson   CeedCheck(l_size >= num_elem * elem_size * num_comp, ceed, CEED_ERROR_DIMENSION, "L-vector size must be at least num_elem * elem_size * num_comp");
624e022e1f8SJeremy L Thompson 
6252b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
626db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
627d1d35e2fSjeremylt   (*rstr)->ref_count  = 1;
628d1d35e2fSjeremylt   (*rstr)->num_elem   = num_elem;
629d1d35e2fSjeremylt   (*rstr)->elem_size  = elem_size;
630d1d35e2fSjeremylt   (*rstr)->num_comp   = num_comp;
631d1d35e2fSjeremylt   (*rstr)->l_size     = l_size;
632*e7f679fcSJeremy L Thompson   (*rstr)->num_block  = num_elem;
633*e7f679fcSJeremy L Thompson   (*rstr)->block_size = 1;
634fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type  = CEED_RESTRICTION_STRIDED;
6352b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
6362b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
637fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
638e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
639d7b241e6Sjeremylt }
640d7b241e6Sjeremylt 
641d7b241e6Sjeremylt /**
642b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
643d7b241e6Sjeremylt 
644ea61e9acSJeremy L Thompson   @param[in]  ceed          Ceed object where the CeedElemRestriction will be created.
645ea61e9acSJeremy L Thompson   @param[in]  num_elem      Number of elements described in the @a offsets array.
646ea61e9acSJeremy L Thompson   @param[in]  elem_size     Size (number of unknowns) per element
647*e7f679fcSJeremy L Thompson   @param[in]  block_size    Number of elements in a block
648ea61e9acSJeremy L Thompson   @param[in]  num_comp      Number of field components per interpolation node (1 for scalar fields)
649fcbe8c06SSebastian Grimberg   @param[in]  comp_stride   Stride between components for the same L-vector "node".
650fcbe8c06SSebastian 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.
651fcbe8c06SSebastian Grimberg   @param[in]  l_size        The size of the L-vector.
652fcbe8c06SSebastian Grimberg                               This vector may be larger than the elements and fields given by this restriction.
653ea61e9acSJeremy L Thompson   @param[in]  mem_type      Memory type of the @a offsets array, see CeedMemType
654ea61e9acSJeremy L Thompson   @param[in]  copy_mode     Copy mode for the @a offsets array, see CeedCopyMode
655fcbe8c06SSebastian Grimberg   @param[in]  offsets       Array of shape [@a num_elem, @a elem_size].
656*e7f679fcSJeremy L Thompson                               Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i,
657*e7f679fcSJeremy L Thompson  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
658*e7f679fcSJeremy L Thompson  for the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
659ea61e9acSJeremy L Thompson   @param[out] rstr          Address of the variable where the newly created CeedElemRestriction will be stored
660d7b241e6Sjeremylt 
661b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
662dfdf5a53Sjeremylt 
6637a982d89SJeremy L. Thompson   @ref Backend
664b11c1e72Sjeremylt  **/
665*e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedInt comp_stride,
6662b730f8bSJeremy L Thompson                                      CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets,
6674ce2993fSjeremylt                                      CeedElemRestriction *rstr) {
668*e7f679fcSJeremy L Thompson   CeedInt *block_offsets;
669*e7f679fcSJeremy L Thompson   CeedInt  num_block = (num_elem / block_size) + !!(num_elem % block_size);
670d7b241e6Sjeremylt 
6715fe0d4faSjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
6725fe0d4faSjeremylt     Ceed delegate;
6736574a04fSJeremy L Thompson 
6742b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
6756402da51SJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
676*e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets,
677*e7f679fcSJeremy L Thompson                                               rstr));
678e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6795fe0d4faSjeremylt   }
680d7b241e6Sjeremylt 
681*e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
6826574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
683*e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
6846574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
6856574a04fSJeremy L Thompson   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
686e022e1f8SJeremy L Thompson 
687*e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
688*e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
689d7b241e6Sjeremylt 
690db002c03SJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
691db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
692d1d35e2fSjeremylt   (*rstr)->ref_count   = 1;
693d1d35e2fSjeremylt   (*rstr)->num_elem    = num_elem;
694d1d35e2fSjeremylt   (*rstr)->elem_size   = elem_size;
695d1d35e2fSjeremylt   (*rstr)->num_comp    = num_comp;
696d1d35e2fSjeremylt   (*rstr)->comp_stride = comp_stride;
697d1d35e2fSjeremylt   (*rstr)->l_size      = l_size;
698*e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
699*e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
70061a27d74SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_STANDARD;
701*e7f679fcSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL, NULL, *rstr));
702d1d35e2fSjeremylt   if (copy_mode == CEED_OWN_POINTER) {
7032b730f8bSJeremy L Thompson     CeedCall(CeedFree(&offsets));
7041d102b48SJeremy L Thompson   }
705e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
706d7b241e6Sjeremylt }
707d7b241e6Sjeremylt 
708b11c1e72Sjeremylt /**
70977d1c127SSebastian Grimberg   @brief Create a blocked oriented CeedElemRestriction, typically only called by backends
71077d1c127SSebastian Grimberg 
71177d1c127SSebastian Grimberg   @param[in]  ceed          Ceed object where the CeedElemRestriction will be created.
71277d1c127SSebastian Grimberg   @param[in]  num_elem      Number of elements described in the @a offsets array.
71377d1c127SSebastian Grimberg   @param[in]  elem_size     Size (number of unknowns) per element
714*e7f679fcSJeremy L Thompson   @param[in]  block_size    Number of elements in a block
71577d1c127SSebastian Grimberg   @param[in]  num_comp      Number of field components per interpolation node (1 for scalar fields)
716fcbe8c06SSebastian Grimberg   @param[in]  comp_stride   Stride between components for the same L-vector "node".
717fcbe8c06SSebastian 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.
718fcbe8c06SSebastian Grimberg   @param[in]  l_size        The size of the L-vector.
719fcbe8c06SSebastian Grimberg                               This vector may be larger than the elements and fields given by this restriction.
72077d1c127SSebastian Grimberg   @param[in]  mem_type      Memory type of the @a offsets array, see CeedMemType
72177d1c127SSebastian Grimberg   @param[in]  copy_mode     Copy mode for the @a offsets array, see CeedCopyMode
722fcbe8c06SSebastian Grimberg   @param[in]  offsets       Array of shape [@a num_elem, @a elem_size].
723fcbe8c06SSebastian Grimberg                             Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i, where
724fcbe8c06SSebastian 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
725fcbe8c06SSebastian Grimberg  the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
726fcbe8c06SSebastian 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.
727fcbe8c06SSebastian Grimberg                               Will also be permuted and padded similarly to @a offsets.
72877d1c127SSebastian Grimberg   @param[out] rstr          Address of the variable where the newly created CeedElemRestriction will be stored
72977d1c127SSebastian Grimberg 
73077d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
73177d1c127SSebastian Grimberg 
73277d1c127SSebastian Grimberg   @ref Backend
73377d1c127SSebastian Grimberg  **/
734*e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp,
735*e7f679fcSJeremy L Thompson                                              CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode,
736*e7f679fcSJeremy L Thompson                                              const CeedInt *offsets, const bool *orients, CeedElemRestriction *rstr) {
737*e7f679fcSJeremy L Thompson   CeedInt *block_offsets;
738*e7f679fcSJeremy L Thompson   bool    *block_orients;
739*e7f679fcSJeremy L Thompson   CeedInt  num_block = (num_elem / block_size) + !!(num_elem % block_size);
74077d1c127SSebastian Grimberg 
741fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreateBlocked) {
74277d1c127SSebastian Grimberg     Ceed delegate;
74377d1c127SSebastian Grimberg 
74477d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
745fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
746*e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode,
74777d1c127SSebastian Grimberg                                                       offsets, orients, rstr));
74877d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
74977d1c127SSebastian Grimberg   }
75077d1c127SSebastian Grimberg 
75177d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
752*e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
75377d1c127SSebastian Grimberg   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
75477d1c127SSebastian Grimberg   CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction component stride must be at least 1");
75577d1c127SSebastian Grimberg 
756*e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
757*e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_orients));
758*e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
759*e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOrients(orients, block_orients, num_block, num_elem, block_size, elem_size));
76077d1c127SSebastian Grimberg 
761fcbe8c06SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
762fcbe8c06SSebastian Grimberg   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
76377d1c127SSebastian Grimberg   (*rstr)->ref_count   = 1;
76477d1c127SSebastian Grimberg   (*rstr)->num_elem    = num_elem;
76577d1c127SSebastian Grimberg   (*rstr)->elem_size   = elem_size;
76677d1c127SSebastian Grimberg   (*rstr)->num_comp    = num_comp;
76777d1c127SSebastian Grimberg   (*rstr)->comp_stride = comp_stride;
76877d1c127SSebastian Grimberg   (*rstr)->l_size      = l_size;
769*e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
770*e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
771fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_ORIENTED;
772*e7f679fcSJeremy L Thompson   CeedCall(
773*e7f679fcSJeremy L Thompson       ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, (const bool *)block_orients, NULL, *rstr));
77477d1c127SSebastian Grimberg   if (copy_mode == CEED_OWN_POINTER) {
77577d1c127SSebastian Grimberg     CeedCall(CeedFree(&offsets));
77677d1c127SSebastian Grimberg   }
77777d1c127SSebastian Grimberg   return CEED_ERROR_SUCCESS;
77877d1c127SSebastian Grimberg }
77977d1c127SSebastian Grimberg 
78077d1c127SSebastian Grimberg /**
78177d1c127SSebastian Grimberg   @brief Create a blocked curl-oriented CeedElemRestriction, typically only called by backends
78277d1c127SSebastian Grimberg 
78377d1c127SSebastian Grimberg   @param[in]  ceed           Ceed object where the CeedElemRestriction will be created.
78477d1c127SSebastian Grimberg   @param[in]  num_elem       Number of elements described in the @a offsets array.
78577d1c127SSebastian Grimberg   @param[in]  elem_size      Size (number of unknowns) per element
786*e7f679fcSJeremy L Thompson   @param[in]  block_size     Number of elements in a block
78777d1c127SSebastian Grimberg   @param[in]  num_comp       Number of field components per interpolation node (1 for scalar fields)
788fcbe8c06SSebastian Grimberg   @param[in]  comp_stride    Stride between components for the same L-vector "node".
789fcbe8c06SSebastian 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.
790fcbe8c06SSebastian Grimberg   @param[in]  l_size         The size of the L-vector.
791fcbe8c06SSebastian Grimberg                                This vector may be larger than the elements and fields given by this restriction.
79277d1c127SSebastian Grimberg   @param[in]  mem_type       Memory type of the @a offsets array, see CeedMemType
79377d1c127SSebastian Grimberg   @param[in]  copy_mode      Copy mode for the @a offsets array, see CeedCopyMode
794fcbe8c06SSebastian Grimberg   @param[in]  offsets        Array of shape [@a num_elem, @a elem_size].
795fcbe8c06SSebastian Grimberg                              Row i holds the ordered list of the offsets (into the input CeedVector) for the unknowns corresponding to element i,
796fcbe8c06SSebastian 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
797fcbe8c06SSebastian Grimberg for the blocksize, which is typically given by the backend. The default reordering is to interlace elements.
7987c1dbaffSSebastian Grimberg   @param[in]  curl_orients Array of shape [@a num_elem, @a 3 * elem_size] representing a row-major tridiagonal matrix (curl_orients[i * 3 * elem_size]
7997c1dbaffSSebastian 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
8007c1dbaffSSebastian Grimberg orientation matrix allows for pairs of face degrees of freedom on elements for H(curl) spaces to be coupled in the element restriction operation,
8017c1dbaffSSebastian Grimberg which is a way to resolve face orientation issues for 3D meshes (https://dl.acm.org/doi/pdf/10.1145/3524456). Will also be permuted and padded
8027c1dbaffSSebastian Grimberg similarly to @a offsets.
80377d1c127SSebastian Grimberg   @param[out] rstr           Address of the variable where the newly created CeedElemRestriction will be stored
80477d1c127SSebastian Grimberg 
80577d1c127SSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
80677d1c127SSebastian Grimberg 
80777d1c127SSebastian Grimberg   @ref Backend
80877d1c127SSebastian Grimberg  **/
809*e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp,
81077d1c127SSebastian Grimberg                                                  CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode,
8110c73c039SSebastian Grimberg                                                  const CeedInt *offsets, const CeedInt8 *curl_orients, CeedElemRestriction *rstr) {
812*e7f679fcSJeremy L Thompson   CeedInt  *block_offsets;
813*e7f679fcSJeremy L Thompson   CeedInt8 *block_curl_orients;
814*e7f679fcSJeremy L Thompson   CeedInt   num_block = (num_elem / block_size) + !!(num_elem % block_size);
81577d1c127SSebastian Grimberg 
816fcbe8c06SSebastian Grimberg   if (!ceed->ElemRestrictionCreateBlocked) {
81777d1c127SSebastian Grimberg     Ceed delegate;
81877d1c127SSebastian Grimberg 
81977d1c127SSebastian Grimberg     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
820fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
821*e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedCurlOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type,
822*e7f679fcSJeremy L Thompson                                                           copy_mode, offsets, curl_orients, rstr));
82377d1c127SSebastian Grimberg     return CEED_ERROR_SUCCESS;
82477d1c127SSebastian Grimberg   }
82577d1c127SSebastian Grimberg 
826*e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
82777d1c127SSebastian Grimberg   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
828*e7f679fcSJeremy L Thompson   CeedCheck(block_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 
832*e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets));
833*e7f679fcSJeremy L Thompson   CeedCall(CeedCalloc(num_block * block_size * 3 * elem_size, &block_curl_orients));
834*e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size));
835*e7f679fcSJeremy L Thompson   CeedCall(CeedPermutePadCurlOrients(curl_orients, block_curl_orients, num_block, num_elem, block_size, 3 * elem_size));
83677d1c127SSebastian Grimberg 
837fcbe8c06SSebastian Grimberg   CeedCall(CeedCalloc(1, rstr));
838fcbe8c06SSebastian 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;
845*e7f679fcSJeremy L Thompson   (*rstr)->num_block   = num_block;
846*e7f679fcSJeremy L Thompson   (*rstr)->block_size  = block_size;
847fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type   = CEED_RESTRICTION_CURL_ORIENTED;
848*e7f679fcSJeremy L Thompson   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL,
849*e7f679fcSJeremy L Thompson                                               (const CeedInt8 *)block_curl_orients, *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
862*e7f679fcSJeremy L Thompson   @param[in]  block_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)
864fcbe8c06SSebastian Grimberg   @param[in]  l_size      The size of the L-vector.
865fcbe8c06SSebastian Grimberg                             This vector may be larger than the elements and fields given by this restriction.
866fcbe8c06SSebastian Grimberg   @param[in]  strides     Array for strides between [nodes, components, elements].
867fcbe8c06SSebastian 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].
868fcbe8c06SSebastian 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 **/
875*e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedSize l_size,
8768621c6c6SJeremy L Thompson                                             const CeedInt strides[3], CeedElemRestriction *rstr) {
877*e7f679fcSJeremy L Thompson   CeedInt num_block = (num_elem / block_size) + !!(num_elem % block_size);
8787509a596Sjeremylt 
8797509a596Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked) {
8807509a596Sjeremylt     Ceed delegate;
8816574a04fSJeremy L Thompson 
8822b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"));
883fcbe8c06SSebastian Grimberg     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionCreateBlocked");
884*e7f679fcSJeremy L Thompson     CeedCall(CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, block_size, num_comp, l_size, strides, rstr));
885e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
8867509a596Sjeremylt   }
8877509a596Sjeremylt 
888*e7f679fcSJeremy L Thompson   CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative");
8896574a04fSJeremy L Thompson   CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1");
890*e7f679fcSJeremy L Thompson   CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1");
8916574a04fSJeremy L Thompson   CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "ElemRestriction must have at least 1 component");
892*e7f679fcSJeremy L Thompson   CeedCheck(l_size >= num_elem * elem_size * num_comp, ceed, CEED_ERROR_DIMENSION, "L-vector size must be at least num_elem * elem_size * num_comp");
893e022e1f8SJeremy L Thompson 
8942b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr));
895db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed));
896d1d35e2fSjeremylt   (*rstr)->ref_count  = 1;
897d1d35e2fSjeremylt   (*rstr)->num_elem   = num_elem;
898d1d35e2fSjeremylt   (*rstr)->elem_size  = elem_size;
899d1d35e2fSjeremylt   (*rstr)->num_comp   = num_comp;
900d1d35e2fSjeremylt   (*rstr)->l_size     = l_size;
901*e7f679fcSJeremy L Thompson   (*rstr)->num_block  = num_block;
902*e7f679fcSJeremy L Thompson   (*rstr)->block_size = block_size;
903fcbe8c06SSebastian Grimberg   (*rstr)->rstr_type  = CEED_RESTRICTION_STRIDED;
9042b730f8bSJeremy L Thompson   CeedCall(CeedMalloc(3, &(*rstr)->strides));
9052b730f8bSJeremy L Thompson   for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i];
906fcbe8c06SSebastian Grimberg   CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr));
907e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
9087509a596Sjeremylt }
9097509a596Sjeremylt 
9107509a596Sjeremylt /**
9117c1dbaffSSebastian Grimberg   @brief Copy the pointer to a CeedElemRestriction and set `CeedElemRestrictionApply()` implementation to use the unsigned version.
912c17ec2beSJeremy L Thompson 
913c17ec2beSJeremy L Thompson   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
914c17ec2beSJeremy L Thompson 
915c17ec2beSJeremy L Thompson   @param[in]     rstr          CeedElemRestriction to create unsigned reference to
916c17ec2beSJeremy L Thompson   @param[in,out] rstr_unsigned Variable to store unsigned CeedElemRestriction
917c17ec2beSJeremy L Thompson 
918c17ec2beSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
919c17ec2beSJeremy L Thompson 
920c17ec2beSJeremy L Thompson   @ref User
921c17ec2beSJeremy L Thompson **/
922c17ec2beSJeremy L Thompson int CeedElemRestrictionCreateUnsignedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unsigned) {
923c17ec2beSJeremy L Thompson   CeedCall(CeedCalloc(1, rstr_unsigned));
924c17ec2beSJeremy L Thompson 
925c17ec2beSJeremy L Thompson   // Copy old rstr
926c17ec2beSJeremy L Thompson   memcpy(*rstr_unsigned, rstr, sizeof(struct CeedElemRestriction_private));
927c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ceed = NULL;
928c17ec2beSJeremy L Thompson   CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unsigned)->ceed));
929c17ec2beSJeremy L Thompson   (*rstr_unsigned)->ref_count = 1;
930c17ec2beSJeremy L Thompson   (*rstr_unsigned)->strides   = NULL;
931c17ec2beSJeremy L Thompson   if (rstr->strides) {
932c17ec2beSJeremy L Thompson     CeedCall(CeedMalloc(3, &(*rstr_unsigned)->strides));
933c17ec2beSJeremy L Thompson     for (CeedInt i = 0; i < 3; i++) (*rstr_unsigned)->strides[i] = rstr->strides[i];
934c17ec2beSJeremy L Thompson   }
9357c1dbaffSSebastian Grimberg   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unsigned)->rstr_base));
936c17ec2beSJeremy L Thompson 
937c17ec2beSJeremy L Thompson   // Override Apply
938c17ec2beSJeremy L Thompson   (*rstr_unsigned)->Apply = rstr->ApplyUnsigned;
939c17ec2beSJeremy L Thompson 
940c17ec2beSJeremy L Thompson   return CEED_ERROR_SUCCESS;
941c17ec2beSJeremy L Thompson }
942c17ec2beSJeremy L Thompson 
943c17ec2beSJeremy L Thompson /**
9447c1dbaffSSebastian Grimberg   @brief Copy the pointer to a CeedElemRestriction and set `CeedElemRestrictionApply()` implementation to use the unoriented version.
9457c1dbaffSSebastian Grimberg 
9467c1dbaffSSebastian Grimberg   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
9477c1dbaffSSebastian Grimberg 
9487c1dbaffSSebastian Grimberg   @param[in]     rstr            CeedElemRestriction to create unoriented reference to
9497c1dbaffSSebastian Grimberg   @param[in,out] rstr_unoriented Variable to store unoriented CeedElemRestriction
9507c1dbaffSSebastian Grimberg 
9517c1dbaffSSebastian Grimberg   @return An error code: 0 - success, otherwise - failure
9527c1dbaffSSebastian Grimberg 
9537c1dbaffSSebastian Grimberg   @ref User
9547c1dbaffSSebastian Grimberg **/
9557c1dbaffSSebastian Grimberg int CeedElemRestrictionCreateUnorientedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unoriented) {
9567c1dbaffSSebastian Grimberg   CeedCall(CeedCalloc(1, rstr_unoriented));
9577c1dbaffSSebastian Grimberg 
9587c1dbaffSSebastian Grimberg   // Copy old rstr
9597c1dbaffSSebastian Grimberg   memcpy(*rstr_unoriented, rstr, sizeof(struct CeedElemRestriction_private));
9607c1dbaffSSebastian Grimberg   (*rstr_unoriented)->ceed = NULL;
9617c1dbaffSSebastian Grimberg   CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unoriented)->ceed));
9627c1dbaffSSebastian Grimberg   (*rstr_unoriented)->ref_count = 1;
9637c1dbaffSSebastian Grimberg   (*rstr_unoriented)->strides   = NULL;
9647c1dbaffSSebastian Grimberg   if (rstr->strides) {
9657c1dbaffSSebastian Grimberg     CeedCall(CeedMalloc(3, &(*rstr_unoriented)->strides));
9667c1dbaffSSebastian Grimberg     for (CeedInt i = 0; i < 3; i++) (*rstr_unoriented)->strides[i] = rstr->strides[i];
9677c1dbaffSSebastian Grimberg   }
9687c1dbaffSSebastian Grimberg   CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unoriented)->rstr_base));
9697c1dbaffSSebastian Grimberg 
9707c1dbaffSSebastian Grimberg   // Override Apply
9717c1dbaffSSebastian Grimberg   (*rstr_unoriented)->Apply = rstr->ApplyUnoriented;
9727c1dbaffSSebastian Grimberg 
9737c1dbaffSSebastian Grimberg   return CEED_ERROR_SUCCESS;
9747c1dbaffSSebastian Grimberg }
9757c1dbaffSSebastian Grimberg 
9767c1dbaffSSebastian Grimberg /**
977ea61e9acSJeremy L Thompson   @brief Copy the pointer to a CeedElemRestriction.
9789fd66db6SSebastian Grimberg 
979ea61e9acSJeremy L Thompson   Both pointers should be destroyed with `CeedElemRestrictionDestroy()`.
9809560d06aSjeremylt 
9819fd66db6SSebastian 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.
9829fd66db6SSebastian Grimberg         This CeedElemRestriction will be destroyed if `rstr_copy` is the only reference to this CeedElemRestriction.
983ea61e9acSJeremy L Thompson 
984ea61e9acSJeremy L Thompson   @param[in]     rstr      CeedElemRestriction to copy reference to
985ea61e9acSJeremy L Thompson   @param[in,out] rstr_copy Variable to store copied reference
9869560d06aSjeremylt 
9879560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
9889560d06aSjeremylt 
9899560d06aSjeremylt   @ref User
9909560d06aSjeremylt **/
9912b730f8bSJeremy L Thompson int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_copy) {
992393ac2cdSJeremy L Thompson   if (rstr != CEED_ELEMRESTRICTION_NONE) CeedCall(CeedElemRestrictionReference(rstr));
9932b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionDestroy(rstr_copy));
9949560d06aSjeremylt   *rstr_copy = rstr;
9959560d06aSjeremylt   return CEED_ERROR_SUCCESS;
9969560d06aSjeremylt }
9979560d06aSjeremylt 
9989560d06aSjeremylt /**
999b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
1000b11c1e72Sjeremylt 
1001ea61e9acSJeremy L Thompson   @param[in]  rstr  CeedElemRestriction
1002ea61e9acSJeremy L Thompson   @param[out] l_vec The address of the L-vector to be created, or NULL
1003ea61e9acSJeremy L Thompson   @param[out] e_vec The address of the E-vector to be created, or NULL
1004b11c1e72Sjeremylt 
1005b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1006dfdf5a53Sjeremylt 
10077a982d89SJeremy L. Thompson   @ref User
1008b11c1e72Sjeremylt **/
10092b730f8bSJeremy L Thompson int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, CeedVector *e_vec) {
1010d2643443SJeremy L Thompson   CeedSize e_size, l_size;
1011d1d35e2fSjeremylt   l_size = rstr->l_size;
1012*e7f679fcSJeremy L Thompson   e_size = rstr->num_block * rstr->block_size * rstr->elem_size * rstr->num_comp;
10132b730f8bSJeremy L Thompson   if (l_vec) CeedCall(CeedVectorCreate(rstr->ceed, l_size, l_vec));
10142b730f8bSJeremy L Thompson   if (e_vec) CeedCall(CeedVectorCreate(rstr->ceed, e_size, e_vec));
1015e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1016d7b241e6Sjeremylt }
1017d7b241e6Sjeremylt 
1018d7b241e6Sjeremylt /**
1019d9e1f99aSValeria Barra   @brief Restrict an L-vector to an E-vector or apply its transpose
1020d7b241e6Sjeremylt 
1021ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
1022ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1023ea61e9acSJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
1024fcbe8c06SSebastian Grimberg   @param[out] ru      Output vector (of shape [@a num_elem * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
1025fcbe8c06SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
1026ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
1027b11c1e72Sjeremylt 
1028b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1029dfdf5a53Sjeremylt 
10307a982d89SJeremy L. Thompson   @ref User
1031b11c1e72Sjeremylt **/
10322b730f8bSJeremy L Thompson int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) {
1033d7b241e6Sjeremylt   CeedInt m, n;
1034d7b241e6Sjeremylt 
1035d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
1036*e7f679fcSJeremy L Thompson     m = rstr->num_block * rstr->block_size * rstr->elem_size * rstr->num_comp;
1037d1d35e2fSjeremylt     n = rstr->l_size;
1038d7b241e6Sjeremylt   } else {
1039d1d35e2fSjeremylt     m = rstr->l_size;
1040*e7f679fcSJeremy L Thompson     n = rstr->num_block * rstr->block_size * rstr->elem_size * rstr->num_comp;
1041d7b241e6Sjeremylt   }
10426574a04fSJeremy L Thompson   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
10436574a04fSJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
10446574a04fSJeremy L Thompson   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
10456574a04fSJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
10462b730f8bSJeremy L Thompson   if (rstr->num_elem > 0) CeedCall(rstr->Apply(rstr, t_mode, u, ru, request));
1047e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1048d7b241e6Sjeremylt }
1049d7b241e6Sjeremylt 
1050d7b241e6Sjeremylt /**
1051d9e1f99aSValeria Barra   @brief Restrict an L-vector to a block of an E-vector or apply its transpose
1052be9261b7Sjeremylt 
1053ea61e9acSJeremy L Thompson   @param[in]  rstr    CeedElemRestriction
1054*e7f679fcSJeremy L Thompson   @param[in]  block   Block number to restrict to/from, i.e. block=0 will handle elements [0 : block_size] and block=3 will handle elements
1055*e7f679fcSJeremy L Thompson [3*block_size : 4*block_size]
1056ea61e9acSJeremy L Thompson   @param[in]  t_mode  Apply restriction or transpose
1057ea61e9acSJeremy L Thompson   @param[in]  u       Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE)
1058*e7f679fcSJeremy L Thompson   @param[out] ru      Output vector (of shape [@a block_size * @a elem_size] when t_mode=@ref CEED_NOTRANSPOSE).
1059fcbe8c06SSebastian Grimberg                         Ordering of the e-vector is decided by the backend.
1060ea61e9acSJeremy L Thompson   @param[in]  request Request or @ref CEED_REQUEST_IMMEDIATE
1061be9261b7Sjeremylt 
1062be9261b7Sjeremylt   @return An error code: 0 - success, otherwise - failure
1063be9261b7Sjeremylt 
10647a982d89SJeremy L. Thompson   @ref Backend
1065be9261b7Sjeremylt **/
10662b730f8bSJeremy L Thompson int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector ru,
10672b730f8bSJeremy L Thompson                                   CeedRequest *request) {
1068be9261b7Sjeremylt   CeedInt m, n;
1069be9261b7Sjeremylt 
10706402da51SJeremy L Thompson   CeedCheck(rstr->ApplyBlock, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement ElemRestrictionApplyBlock");
10716402da51SJeremy L Thompson 
1072d1d35e2fSjeremylt   if (t_mode == CEED_NOTRANSPOSE) {
1073*e7f679fcSJeremy L Thompson     m = rstr->block_size * rstr->elem_size * rstr->num_comp;
1074d1d35e2fSjeremylt     n = rstr->l_size;
1075be9261b7Sjeremylt   } else {
1076d1d35e2fSjeremylt     m = rstr->l_size;
1077*e7f679fcSJeremy L Thompson     n = rstr->block_size * rstr->elem_size * rstr->num_comp;
1078be9261b7Sjeremylt   }
10796574a04fSJeremy L Thompson   CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION,
10806574a04fSJeremy L Thompson             "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n);
10816574a04fSJeremy L Thompson   CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION,
10826574a04fSJeremy L Thompson             "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n);
1083*e7f679fcSJeremy L Thompson   CeedCheck(rstr->block_size * block <= rstr->num_elem, rstr->ceed, CEED_ERROR_DIMENSION,
1084*e7f679fcSJeremy L Thompson             "Cannot retrieve block %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", block, rstr->block_size * block,
10856574a04fSJeremy L Thompson             rstr->num_elem);
10862b730f8bSJeremy L Thompson   CeedCall(rstr->ApplyBlock(rstr, block, t_mode, u, ru, request));
1087e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1088be9261b7Sjeremylt }
1089be9261b7Sjeremylt 
1090be9261b7Sjeremylt /**
1091b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedElemRestriction
1092b7c9bbdaSJeremy L Thompson 
1093ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
1094b7c9bbdaSJeremy L Thompson   @param[out] ceed Variable to store Ceed
1095b7c9bbdaSJeremy L Thompson 
1096b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1097b7c9bbdaSJeremy L Thompson 
1098b7c9bbdaSJeremy L Thompson   @ref Advanced
1099b7c9bbdaSJeremy L Thompson **/
1100b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
1101b7c9bbdaSJeremy L Thompson   *ceed = rstr->ceed;
1102b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1103b7c9bbdaSJeremy L Thompson }
1104b7c9bbdaSJeremy L Thompson 
1105b7c9bbdaSJeremy L Thompson /**
1106d979a051Sjeremylt   @brief Get the L-vector component stride
1107a681ae63Sjeremylt 
1108ea61e9acSJeremy L Thompson   @param[in]  rstr        CeedElemRestriction
1109d1d35e2fSjeremylt   @param[out] comp_stride Variable to store component stride
1110a681ae63Sjeremylt 
1111a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1112a681ae63Sjeremylt 
1113b7c9bbdaSJeremy L Thompson   @ref Advanced
1114a681ae63Sjeremylt **/
11152b730f8bSJeremy L Thompson int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, CeedInt *comp_stride) {
1116d1d35e2fSjeremylt   *comp_stride = rstr->comp_stride;
1117e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1118a681ae63Sjeremylt }
1119a681ae63Sjeremylt 
1120a681ae63Sjeremylt /**
1121a681ae63Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
1122a681ae63Sjeremylt 
1123ea61e9acSJeremy L Thompson   @param[in] rstr      CeedElemRestriction
1124d1d35e2fSjeremylt   @param[out] num_elem Variable to store number of elements
1125a681ae63Sjeremylt 
1126a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1127a681ae63Sjeremylt 
1128b7c9bbdaSJeremy L Thompson   @ref Advanced
1129a681ae63Sjeremylt **/
11302b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, CeedInt *num_elem) {
1131d1d35e2fSjeremylt   *num_elem = rstr->num_elem;
1132e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1133a681ae63Sjeremylt }
1134a681ae63Sjeremylt 
1135a681ae63Sjeremylt /**
1136a681ae63Sjeremylt   @brief Get the size of elements in the CeedElemRestriction
1137a681ae63Sjeremylt 
1138ea61e9acSJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
1139d1d35e2fSjeremylt   @param[out] elem_size Variable to store size of elements
1140a681ae63Sjeremylt 
1141a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1142a681ae63Sjeremylt 
1143b7c9bbdaSJeremy L Thompson   @ref Advanced
1144a681ae63Sjeremylt **/
11452b730f8bSJeremy L Thompson int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, CeedInt *elem_size) {
1146d1d35e2fSjeremylt   *elem_size = rstr->elem_size;
1147e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1148a681ae63Sjeremylt }
1149a681ae63Sjeremylt 
1150a681ae63Sjeremylt /**
1151d979a051Sjeremylt   @brief Get the size of the l-vector for a CeedElemRestriction
1152a681ae63Sjeremylt 
1153ea61e9acSJeremy L Thompson   @param[in]  rstr   CeedElemRestriction
1154d1d35e2fSjeremylt   @param[out] l_size Variable to store number of nodes
1155a681ae63Sjeremylt 
1156a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1157a681ae63Sjeremylt 
1158b7c9bbdaSJeremy L Thompson   @ref Advanced
1159a681ae63Sjeremylt **/
11602b730f8bSJeremy L Thompson int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, CeedSize *l_size) {
1161d1d35e2fSjeremylt   *l_size = rstr->l_size;
1162e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1163a681ae63Sjeremylt }
1164a681ae63Sjeremylt 
1165a681ae63Sjeremylt /**
1166ea61e9acSJeremy L Thompson   @brief Get the number of components in the elements of a CeedElemRestriction
1167a681ae63Sjeremylt 
1168ea61e9acSJeremy L Thompson   @param[in]  rstr     CeedElemRestriction
1169d1d35e2fSjeremylt   @param[out] num_comp Variable to store number of components
1170a681ae63Sjeremylt 
1171a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1172a681ae63Sjeremylt 
1173b7c9bbdaSJeremy L Thompson   @ref Advanced
1174a681ae63Sjeremylt **/
11752b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, CeedInt *num_comp) {
1176d1d35e2fSjeremylt   *num_comp = rstr->num_comp;
1177e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1178a681ae63Sjeremylt }
1179a681ae63Sjeremylt 
1180a681ae63Sjeremylt /**
1181a681ae63Sjeremylt   @brief Get the number of blocks in a CeedElemRestriction
1182a681ae63Sjeremylt 
1183ea61e9acSJeremy L Thompson   @param[in]  rstr      CeedElemRestriction
1184d1d35e2fSjeremylt   @param[out] num_block Variable to store number of blocks
1185a681ae63Sjeremylt 
1186a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1187a681ae63Sjeremylt 
1188b7c9bbdaSJeremy L Thompson   @ref Advanced
1189a681ae63Sjeremylt **/
11902b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, CeedInt *num_block) {
1191*e7f679fcSJeremy L Thompson   *num_block = rstr->num_block;
1192e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1193a681ae63Sjeremylt }
1194a681ae63Sjeremylt 
1195a681ae63Sjeremylt /**
1196a681ae63Sjeremylt   @brief Get the size of blocks in the CeedElemRestriction
1197a681ae63Sjeremylt 
1198ea61e9acSJeremy L Thompson   @param[in]  rstr       CeedElemRestriction
1199*e7f679fcSJeremy L Thompson   @param[out] block_size Variable to store size of blocks
1200a681ae63Sjeremylt 
1201a681ae63Sjeremylt   @return An error code: 0 - success, otherwise - failure
1202a681ae63Sjeremylt 
1203b7c9bbdaSJeremy L Thompson   @ref Advanced
1204a681ae63Sjeremylt **/
1205*e7f679fcSJeremy L Thompson int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, CeedInt *block_size) {
1206*e7f679fcSJeremy L Thompson   *block_size = rstr->block_size;
1207e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1208a681ae63Sjeremylt }
1209a681ae63Sjeremylt 
1210a681ae63Sjeremylt /**
1211d9e1f99aSValeria Barra   @brief Get the multiplicity of nodes in a CeedElemRestriction
12121469ee4dSjeremylt 
1213ea61e9acSJeremy L Thompson   @param[in]  rstr CeedElemRestriction
1214d1d35e2fSjeremylt   @param[out] mult Vector to store multiplicity (of size l_size)
12151469ee4dSjeremylt 
12161469ee4dSjeremylt   @return An error code: 0 - success, otherwise - failure
12171469ee4dSjeremylt 
12187a982d89SJeremy L. Thompson   @ref User
12191469ee4dSjeremylt **/
12202b730f8bSJeremy L Thompson int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, CeedVector mult) {
1221d1d35e2fSjeremylt   CeedVector e_vec;
12221469ee4dSjeremylt 
122325509ebbSRezgar Shakeri   // Create e_vec to hold intermediate computation in E^T (E 1)
12242b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionCreateVector(rstr, NULL, &e_vec));
12251469ee4dSjeremylt 
122625509ebbSRezgar Shakeri   // Compute e_vec = E * 1
12272b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 1.0));
12282b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, CEED_REQUEST_IMMEDIATE));
122925509ebbSRezgar Shakeri   // Compute multiplicity, mult = E^T * e_vec = E^T (E 1)
12302b730f8bSJeremy L Thompson   CeedCall(CeedVectorSetValue(mult, 0.0));
12312b730f8bSJeremy L Thompson   CeedCall(CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, CEED_REQUEST_IMMEDIATE));
12321469ee4dSjeremylt   // Cleanup
12332b730f8bSJeremy L Thompson   CeedCall(CeedVectorDestroy(&e_vec));
1234e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
12351469ee4dSjeremylt }
12361469ee4dSjeremylt 
12371469ee4dSjeremylt /**
1238f02ca4a2SJed Brown   @brief View a CeedElemRestriction
1239f02ca4a2SJed Brown 
1240f02ca4a2SJed Brown   @param[in] rstr   CeedElemRestriction to view
1241f02ca4a2SJed Brown   @param[in] stream Stream to write; typically stdout/stderr or a file
1242f02ca4a2SJed Brown 
1243f02ca4a2SJed Brown   @return Error code: 0 - success, otherwise - failure
1244f02ca4a2SJed Brown 
12457a982d89SJeremy L. Thompson   @ref User
1246f02ca4a2SJed Brown **/
1247f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) {
12487509a596Sjeremylt   char stridesstr[500];
12492b730f8bSJeremy L Thompson   if (rstr->strides) {
12502b730f8bSJeremy L Thompson     sprintf(stridesstr, "[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "]", rstr->strides[0], rstr->strides[1], rstr->strides[2]);
12512b730f8bSJeremy L Thompson   } else {
1252990fdeb6SJeremy L Thompson     sprintf(stridesstr, "%" CeedInt_FMT, rstr->comp_stride);
12532b730f8bSJeremy L Thompson   }
12547509a596Sjeremylt 
12552b730f8bSJeremy L Thompson   fprintf(stream, "%sCeedElemRestriction from (%td, %" CeedInt_FMT ") to %" CeedInt_FMT " elements with %" CeedInt_FMT " nodes each and %s %s\n",
1256*e7f679fcSJeremy L Thompson           rstr->block_size > 1 ? "Blocked " : "", rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size,
1257d979a051Sjeremylt           rstr->strides ? "strides" : "component stride", stridesstr);
1258e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1259f02ca4a2SJed Brown }
1260f02ca4a2SJed Brown 
1261f02ca4a2SJed Brown /**
1262b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
1263b11c1e72Sjeremylt 
1264ea61e9acSJeremy L Thompson   @param[in,out] rstr CeedElemRestriction to destroy
1265b11c1e72Sjeremylt 
1266b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1267dfdf5a53Sjeremylt 
12687a982d89SJeremy L. Thompson   @ref User
1269b11c1e72Sjeremylt **/
12704ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
1271393ac2cdSJeremy L Thompson   if (!*rstr || *rstr == CEED_ELEMRESTRICTION_NONE || --(*rstr)->ref_count > 0) {
1272ad6481ceSJeremy L Thompson     *rstr = NULL;
1273ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
1274ad6481ceSJeremy L Thompson   }
12756574a04fSJeremy L Thompson   CeedCheck((*rstr)->num_readers == 0, (*rstr)->ceed, CEED_ERROR_ACCESS,
12766574a04fSJeremy L Thompson             "Cannot destroy CeedElemRestriction, a process has read access to the offset data");
1277c17ec2beSJeremy L Thompson 
1278c17ec2beSJeremy L Thompson   // Only destroy backend data once between rstr and unsigned copy
12797c1dbaffSSebastian Grimberg   if ((*rstr)->rstr_base) CeedCall(CeedElemRestrictionDestroy(&(*rstr)->rstr_base));
1280c17ec2beSJeremy L Thompson   else if ((*rstr)->Destroy) CeedCall((*rstr)->Destroy(*rstr));
1281c17ec2beSJeremy L Thompson 
12822b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*rstr)->strides));
12832b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*rstr)->ceed));
12842b730f8bSJeremy L Thompson   CeedCall(CeedFree(rstr));
1285e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1286d7b241e6Sjeremylt }
1287d7b241e6Sjeremylt 
1288d7b241e6Sjeremylt /// @}
1289