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 /** 25ca94c3ddSJeremy L Thompson @brief Permute and pad offsets for a blocked `CeedElemRestriction` 267a982d89SJeremy L. Thompson 27ca94c3ddSJeremy L Thompson @param[in] offsets Array of shape `[num_elem, elem_size]` 28ca94c3ddSJeremy L Thompson @param[out] block_offsets Array of permuted and padded array values of shape `[num_block, elem_size, block_size]` 29e7f679fcSJeremy L Thompson @param[in] num_block Number of blocks 30ea61e9acSJeremy L Thompson @param[in] num_elem Number of elements 31e7f679fcSJeremy 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 **/ 38e7f679fcSJeremy L Thompson int CeedPermutePadOffsets(const CeedInt *offsets, CeedInt *block_offsets, CeedInt num_block, CeedInt num_elem, CeedInt block_size, 39e7f679fcSJeremy L Thompson CeedInt elem_size) { 40e7f679fcSJeremy L Thompson for (CeedInt e = 0; e < num_block * block_size; e += block_size) { 41e7f679fcSJeremy L Thompson for (CeedInt j = 0; j < block_size; j++) { 422b730f8bSJeremy L Thompson for (CeedInt k = 0; k < elem_size; k++) { 43e7f679fcSJeremy 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 /** 51ca94c3ddSJeremy L Thompson @brief Permute and pad orientations for a blocked `CeedElemRestriction` 5277d1c127SSebastian Grimberg 53ca94c3ddSJeremy L Thompson @param[in] orients Array of shape `[num_elem, elem_size]` 54ca94c3ddSJeremy L Thompson @param[out] block_orients Array of permuted and padded array values of shape `[num_block, elem_size, block_size]` 55e7f679fcSJeremy L Thompson @param[in] num_block Number of blocks 5677d1c127SSebastian Grimberg @param[in] num_elem Number of elements 57e7f679fcSJeremy 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 **/ 64e7f679fcSJeremy L Thompson int CeedPermutePadOrients(const bool *orients, bool *block_orients, CeedInt num_block, CeedInt num_elem, CeedInt block_size, CeedInt elem_size) { 65e7f679fcSJeremy L Thompson for (CeedInt e = 0; e < num_block * block_size; e += block_size) { 66e7f679fcSJeremy L Thompson for (CeedInt j = 0; j < block_size; j++) { 6777d1c127SSebastian Grimberg for (CeedInt k = 0; k < elem_size; k++) { 68e7f679fcSJeremy 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 /** 76ca94c3ddSJeremy L Thompson @brief Permute and pad curl-conforming orientations for a blocked `CeedElemRestriction` 770c73c039SSebastian Grimberg 785c7e0f51SSebastian Grimberg @param[in] curl_orients Array of shape `[num_elem, elem_size]` 79ca94c3ddSJeremy L Thompson @param[out] block_curl_orients Array of permuted and padded array values of shape `[num_block, elem_size, block_size]` 80e7f679fcSJeremy L Thompson @param[in] num_block Number of blocks 810c73c039SSebastian Grimberg @param[in] num_elem Number of elements 82e7f679fcSJeremy 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 **/ 89e7f679fcSJeremy 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) { 91e7f679fcSJeremy L Thompson for (CeedInt e = 0; e < num_block * block_size; e += block_size) { 92e7f679fcSJeremy L Thompson for (CeedInt j = 0; j < block_size; j++) { 930c73c039SSebastian Grimberg for (CeedInt k = 0; k < elem_size; k++) { 94e7f679fcSJeremy 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 /** 110ca94c3ddSJeremy L Thompson @brief Get the type of a `CeedElemRestriction` 111a681ae63Sjeremylt 112ca94c3ddSJeremy L Thompson @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 /** 125ca94c3ddSJeremy L Thompson @brief Get the strided status of a `CeedElemRestriction` 126fcbe8c06SSebastian Grimberg 127ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 128ca94c3ddSJeremy L Thompson @param[out] is_strided Variable to store strided status 129ca94c3ddSJeremy L Thompson 130ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 131ca94c3ddSJeremy L Thompson 132ca94c3ddSJeremy L Thompson @ref Backend 133fcbe8c06SSebastian Grimberg **/ 134fcbe8c06SSebastian Grimberg int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) { 135fcbe8c06SSebastian Grimberg *is_strided = (rstr->rstr_type == CEED_RESTRICTION_STRIDED); 136fcbe8c06SSebastian Grimberg return CEED_ERROR_SUCCESS; 137fcbe8c06SSebastian Grimberg } 138fcbe8c06SSebastian Grimberg 139fcbe8c06SSebastian Grimberg /** 140ca94c3ddSJeremy L Thompson @brief Get the points status of a `CeedElemRestriction` 1413ac8f562SJeremy L Thompson 142ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 143ca94c3ddSJeremy L Thompson @param[out] is_points Variable to store points status 144ca94c3ddSJeremy L Thompson 145ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 146ca94c3ddSJeremy L Thompson 147ca94c3ddSJeremy L Thompson @ref Backend 1483ac8f562SJeremy L Thompson **/ 1493ac8f562SJeremy L Thompson int CeedElemRestrictionIsPoints(CeedElemRestriction rstr, bool *is_points) { 1503ac8f562SJeremy L Thompson *is_points = (rstr->rstr_type == CEED_RESTRICTION_POINTS); 1513ac8f562SJeremy L Thompson return CEED_ERROR_SUCCESS; 1523ac8f562SJeremy L Thompson } 1533ac8f562SJeremy L Thompson 1543ac8f562SJeremy L Thompson /** 155ca94c3ddSJeremy L Thompson @brief Check if two `CeedElemRestriction` created with @ref CeedElemRestrictionCreateAtPoints() and use the same points per element 15648acf710SJeremy L Thompson 157ca94c3ddSJeremy L Thompson @param[in] rstr_a First `CeedElemRestriction` 158ca94c3ddSJeremy L Thompson @param[in] rstr_b Second `CeedElemRestriction` 15948acf710SJeremy L Thompson @param[out] are_compatible Variable to store compatibility status 160ca94c3ddSJeremy L Thompson 161ca94c3ddSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 162ca94c3ddSJeremy L Thompson 163ca94c3ddSJeremy L Thompson @ref Backend 16448acf710SJeremy L Thompson **/ 16548acf710SJeremy L Thompson int CeedElemRestrictionAtPointsAreCompatible(CeedElemRestriction rstr_a, CeedElemRestriction rstr_b, bool *are_compatible) { 16648acf710SJeremy L Thompson CeedInt num_elem_a, num_elem_b, num_points_a, num_points_b; 16748acf710SJeremy L Thompson 16848acf710SJeremy L Thompson // Cannot compare non-points restrictions 169ca94c3ddSJeremy L Thompson CeedCheck(rstr_a->rstr_type == CEED_RESTRICTION_POINTS, rstr_a->ceed, CEED_ERROR_UNSUPPORTED, "First CeedElemRestriction must be AtPoints"); 170ca94c3ddSJeremy L Thompson CeedCheck(rstr_b->rstr_type == CEED_RESTRICTION_POINTS, rstr_b->ceed, CEED_ERROR_UNSUPPORTED, "Second CeedElemRestriction must be AtPoints"); 17148acf710SJeremy L Thompson 17248acf710SJeremy L Thompson CeedCall(CeedElemRestrictionGetNumElements(rstr_a, &num_elem_a)); 17348acf710SJeremy L Thompson CeedCall(CeedElemRestrictionGetNumElements(rstr_b, &num_elem_b)); 17448acf710SJeremy L Thompson CeedCall(CeedElemRestrictionGetNumPoints(rstr_a, &num_points_a)); 17548acf710SJeremy L Thompson CeedCall(CeedElemRestrictionGetNumPoints(rstr_b, &num_points_b)); 17648acf710SJeremy L Thompson 17748acf710SJeremy L Thompson // Check size and contents of offsets arrays 17848acf710SJeremy L Thompson *are_compatible = true; 17948acf710SJeremy L Thompson if (num_elem_a != num_elem_b) *are_compatible = false; 18048acf710SJeremy L Thompson if (num_points_a != num_points_b) *are_compatible = false; 18148acf710SJeremy L Thompson if (*are_compatible) { 18248acf710SJeremy L Thompson const CeedInt *offsets_a, *offsets_b; 18348acf710SJeremy L Thompson 18448acf710SJeremy L Thompson CeedCall(CeedElemRestrictionGetOffsets(rstr_a, CEED_MEM_HOST, &offsets_a)); 18548acf710SJeremy L Thompson CeedCall(CeedElemRestrictionGetOffsets(rstr_b, CEED_MEM_HOST, &offsets_b)); 18648acf710SJeremy L Thompson for (CeedInt i = 0; i < num_elem_a + 1 + num_points_a; i++) *are_compatible &= offsets_a[i] == offsets_b[i]; 18748acf710SJeremy L Thompson CeedCall(CeedElemRestrictionRestoreOffsets(rstr_a, &offsets_a)); 18848acf710SJeremy L Thompson CeedCall(CeedElemRestrictionRestoreOffsets(rstr_b, &offsets_b)); 18948acf710SJeremy L Thompson } 19048acf710SJeremy L Thompson return CEED_ERROR_SUCCESS; 19148acf710SJeremy L Thompson } 19248acf710SJeremy L Thompson 19348acf710SJeremy L Thompson /** 194ca94c3ddSJeremy L Thompson @brief Get the strides of a strided `CeedElemRestriction` 1957a982d89SJeremy L. Thompson 196ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 197a681ae63Sjeremylt @param[out] strides Variable to store strides array 1987a982d89SJeremy L. Thompson 1997a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 2007a982d89SJeremy L. Thompson 2017a982d89SJeremy L. Thompson @ref Backend 2027a982d89SJeremy L. Thompson **/ 2032b730f8bSJeremy L Thompson int CeedElemRestrictionGetStrides(CeedElemRestriction rstr, CeedInt (*strides)[3]) { 204ca94c3ddSJeremy L Thompson CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "CeedElemRestriction has no stride data"); 2052b730f8bSJeremy L Thompson for (CeedInt i = 0; i < 3; i++) (*strides)[i] = rstr->strides[i]; 206e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2077a982d89SJeremy L. Thompson } 2087a982d89SJeremy L. Thompson 2097a982d89SJeremy L. Thompson /** 210ca94c3ddSJeremy L Thompson @brief Get the backend stride status of a `CeedElemRestriction` 21177d1c127SSebastian Grimberg 212ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 21377d1c127SSebastian Grimberg @param[out] has_backend_strides Variable to store stride status 21477d1c127SSebastian Grimberg 21577d1c127SSebastian Grimberg @return An error code: 0 - success, otherwise - failure 21677d1c127SSebastian Grimberg 21777d1c127SSebastian Grimberg @ref Backend 21877d1c127SSebastian Grimberg **/ 21977d1c127SSebastian Grimberg int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, bool *has_backend_strides) { 220ca94c3ddSJeremy L Thompson CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "CeedElemRestriction has no stride data"); 22177d1c127SSebastian Grimberg *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) && 22277d1c127SSebastian Grimberg (rstr->strides[2] == CEED_STRIDES_BACKEND[2])); 22377d1c127SSebastian Grimberg return CEED_ERROR_SUCCESS; 22477d1c127SSebastian Grimberg } 22577d1c127SSebastian Grimberg 22677d1c127SSebastian Grimberg /** 227ca94c3ddSJeremy L Thompson @brief Get read-only access to a `CeedElemRestriction` offsets array by @ref CeedMemType 228bd33150aSjeremylt 229ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` to retrieve offsets 230fcbe8c06SSebastian Grimberg @param[in] mem_type Memory type on which to access the array. 231fcbe8c06SSebastian Grimberg If the backend uses a different memory type, this will perform a copy (possibly cached). 232ca94c3ddSJeremy L Thompson @param[out] offsets Array on memory type `mem_type` 233bd33150aSjeremylt 234bd33150aSjeremylt @return An error code: 0 - success, otherwise - failure 235bd33150aSjeremylt 236bd33150aSjeremylt @ref User 237bd33150aSjeremylt **/ 2382b730f8bSJeremy L Thompson int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) { 2397c1dbaffSSebastian Grimberg if (rstr->rstr_base) { 2407c1dbaffSSebastian Grimberg CeedCall(CeedElemRestrictionGetOffsets(rstr->rstr_base, mem_type, offsets)); 241c17ec2beSJeremy L Thompson } else { 242ca94c3ddSJeremy L Thompson CeedCheck(rstr->GetOffsets, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support CeedElemRestrictionGetOffsets"); 2432b730f8bSJeremy L Thompson CeedCall(rstr->GetOffsets(rstr, mem_type, offsets)); 244d1d35e2fSjeremylt rstr->num_readers++; 245c17ec2beSJeremy L Thompson } 246e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 247430758c8SJeremy L Thompson } 248430758c8SJeremy L Thompson 249430758c8SJeremy L Thompson /** 250ca94c3ddSJeremy L Thompson @brief Restore an offsets array obtained using @ref CeedElemRestrictionGetOffsets() 251430758c8SJeremy L Thompson 252ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` to restore 253ea61e9acSJeremy L Thompson @param[in] offsets Array of offset data 254430758c8SJeremy L Thompson 255430758c8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 256430758c8SJeremy L Thompson 257430758c8SJeremy L Thompson @ref User 258430758c8SJeremy L Thompson **/ 2592b730f8bSJeremy L Thompson int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr, const CeedInt **offsets) { 2607c1dbaffSSebastian Grimberg if (rstr->rstr_base) { 2617c1dbaffSSebastian Grimberg CeedCall(CeedElemRestrictionRestoreOffsets(rstr->rstr_base, offsets)); 262c17ec2beSJeremy L Thompson } else { 263430758c8SJeremy L Thompson *offsets = NULL; 264d1d35e2fSjeremylt rstr->num_readers--; 265c17ec2beSJeremy L Thompson } 266e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 267bd33150aSjeremylt } 268bd33150aSjeremylt 269bd33150aSjeremylt /** 270ca94c3ddSJeremy L Thompson @brief Get read-only access to a `CeedElemRestriction` orientations array by @ref CeedMemType 2713ac43b2cSJeremy L Thompson 272ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` to retrieve orientations 273fcbe8c06SSebastian Grimberg @param[in] mem_type Memory type on which to access the array. 274fcbe8c06SSebastian Grimberg If the backend uses a different memory type, this will perform a copy (possibly cached). 275ca94c3ddSJeremy L Thompson @param[out] orients Array on memory type `mem_type` 2763ac43b2cSJeremy L Thompson 2773ac43b2cSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 2783ac43b2cSJeremy L Thompson 27977d1c127SSebastian Grimberg @ref User 2803ac43b2cSJeremy L Thompson **/ 28177d1c127SSebastian Grimberg int CeedElemRestrictionGetOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const bool **orients) { 282ca94c3ddSJeremy L Thompson CeedCheck(rstr->GetOrientations, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support CeedElemRestrictionGetOrientations"); 28377d1c127SSebastian Grimberg CeedCall(rstr->GetOrientations(rstr, mem_type, orients)); 28477d1c127SSebastian Grimberg rstr->num_readers++; 285e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2863ac43b2cSJeremy L Thompson } 2873ac43b2cSJeremy L Thompson 2883ac43b2cSJeremy L Thompson /** 289ca94c3ddSJeremy L Thompson @brief Restore an orientations array obtained using @ref CeedElemRestrictionGetOrientations() 290b435c5a6Srezgarshakeri 291ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` to restore 29277d1c127SSebastian Grimberg @param[in] orients Array of orientation data 293b435c5a6Srezgarshakeri 294b435c5a6Srezgarshakeri @return An error code: 0 - success, otherwise - failure 295b435c5a6Srezgarshakeri 29677d1c127SSebastian Grimberg @ref User 297b435c5a6Srezgarshakeri **/ 29877d1c127SSebastian Grimberg int CeedElemRestrictionRestoreOrientations(CeedElemRestriction rstr, const bool **orients) { 29977d1c127SSebastian Grimberg *orients = NULL; 30077d1c127SSebastian Grimberg rstr->num_readers--; 301b435c5a6Srezgarshakeri return CEED_ERROR_SUCCESS; 302b435c5a6Srezgarshakeri } 303b435c5a6Srezgarshakeri 304b435c5a6Srezgarshakeri /** 305ca94c3ddSJeremy L Thompson @brief Get read-only access to a `CeedElemRestriction` curl-conforming orientations array by @ref CeedMemType 3067a982d89SJeremy L. Thompson 307ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` to retrieve curl-conforming orientations 308fcbe8c06SSebastian Grimberg @param[in] mem_type Memory type on which to access the array. 309fcbe8c06SSebastian Grimberg If the backend uses a different memory type, this will perform a copy (possibly cached). 310ca94c3ddSJeremy L Thompson @param[out] curl_orients Array on memory type `mem_type` 3117a982d89SJeremy L. Thompson 3127a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3137a982d89SJeremy L. Thompson 31477d1c127SSebastian Grimberg @ref User 3157a982d89SJeremy L. Thompson **/ 3160c73c039SSebastian Grimberg int CeedElemRestrictionGetCurlOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt8 **curl_orients) { 317ca94c3ddSJeremy L Thompson CeedCheck(rstr->GetCurlOrientations, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support CeedElemRestrictionGetCurlOrientations"); 31877d1c127SSebastian Grimberg CeedCall(rstr->GetCurlOrientations(rstr, mem_type, curl_orients)); 31977d1c127SSebastian Grimberg rstr->num_readers++; 32077d1c127SSebastian Grimberg return CEED_ERROR_SUCCESS; 32177d1c127SSebastian Grimberg } 32277d1c127SSebastian Grimberg 32377d1c127SSebastian Grimberg /** 324ca94c3ddSJeremy L Thompson @brief Restore an orientations array obtained using @ref CeedElemRestrictionGetCurlOrientations() 32577d1c127SSebastian Grimberg 326ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` to restore 32777d1c127SSebastian Grimberg @param[in] curl_orients Array of orientation data 32877d1c127SSebastian Grimberg 32977d1c127SSebastian Grimberg @return An error code: 0 - success, otherwise - failure 33077d1c127SSebastian Grimberg 33177d1c127SSebastian Grimberg @ref User 33277d1c127SSebastian Grimberg **/ 3330c73c039SSebastian Grimberg int CeedElemRestrictionRestoreCurlOrientations(CeedElemRestriction rstr, const CeedInt8 **curl_orients) { 33477d1c127SSebastian Grimberg *curl_orients = NULL; 33577d1c127SSebastian Grimberg rstr->num_readers--; 336e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3377a982d89SJeremy L. Thompson } 3387a982d89SJeremy L. Thompson 3397a982d89SJeremy L. Thompson /** 34049fd234cSJeremy L Thompson 341ca94c3ddSJeremy L Thompson @brief Get the E-vector layout of a `CeedElemRestriction` 34249fd234cSJeremy L Thompson 343ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 344ca94c3ddSJeremy L Thompson @param[out] layout Variable to store layout array, stored as `[nodes, components, elements]`. 345ca94c3ddSJeremy 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]`. 34649fd234cSJeremy L Thompson 34749fd234cSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 34849fd234cSJeremy L Thompson 34949fd234cSJeremy L Thompson @ref Backend 35049fd234cSJeremy L Thompson **/ 3512b730f8bSJeremy L Thompson int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, CeedInt (*layout)[3]) { 352ca94c3ddSJeremy L Thompson CeedCheck(rstr->layout[0], rstr->ceed, CEED_ERROR_MINOR, "CeedElemRestriction has no layout data"); 3532b730f8bSJeremy L Thompson for (CeedInt i = 0; i < 3; i++) (*layout)[i] = rstr->layout[i]; 354e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 35549fd234cSJeremy L Thompson } 35649fd234cSJeremy L Thompson 35749fd234cSJeremy L Thompson /** 35849fd234cSJeremy L Thompson 359ca94c3ddSJeremy L Thompson @brief Set the E-vector layout of a `CeedElemRestriction` 36049fd234cSJeremy L Thompson 361ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 362ca94c3ddSJeremy L Thompson @param[in] layout Variable to containing layout array, stored as `[nodes, components, elements]`. 363ca94c3ddSJeremy 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]`. 36449fd234cSJeremy L Thompson 36549fd234cSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 36649fd234cSJeremy L Thompson 36749fd234cSJeremy L Thompson @ref Backend 36849fd234cSJeremy L Thompson **/ 3692b730f8bSJeremy L Thompson int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, CeedInt layout[3]) { 3702b730f8bSJeremy L Thompson for (CeedInt i = 0; i < 3; i++) rstr->layout[i] = layout[i]; 371e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 37249fd234cSJeremy L Thompson } 37349fd234cSJeremy L Thompson 37449fd234cSJeremy L Thompson /** 375ca94c3ddSJeremy L Thompson @brief Get the backend data of a `CeedElemRestriction` 3767a982d89SJeremy L. Thompson 377ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 3787a982d89SJeremy L. Thompson @param[out] data Variable to store data 3797a982d89SJeremy L. Thompson 3807a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3817a982d89SJeremy L. Thompson 3827a982d89SJeremy L. Thompson @ref Backend 3837a982d89SJeremy L. Thompson **/ 384777ff853SJeremy L Thompson int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) { 385777ff853SJeremy L Thompson *(void **)data = rstr->data; 386e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3877a982d89SJeremy L. Thompson } 3887a982d89SJeremy L. Thompson 3897a982d89SJeremy L. Thompson /** 390ca94c3ddSJeremy L Thompson @brief Set the backend data of a `CeedElemRestriction` 3917a982d89SJeremy L. Thompson 392ca94c3ddSJeremy L Thompson @param[in,out] rstr `CeedElemRestriction` 393ea61e9acSJeremy L Thompson @param[in] data Data to set 3947a982d89SJeremy L. Thompson 3957a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 3967a982d89SJeremy L. Thompson 3977a982d89SJeremy L. Thompson @ref Backend 3987a982d89SJeremy L. Thompson **/ 399777ff853SJeremy L Thompson int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) { 400777ff853SJeremy L Thompson rstr->data = data; 401e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 4027a982d89SJeremy L. Thompson } 4037a982d89SJeremy L. Thompson 40434359f16Sjeremylt /** 405ca94c3ddSJeremy L Thompson @brief Increment the reference counter for a `CeedElemRestriction` 40634359f16Sjeremylt 407ca94c3ddSJeremy L Thompson @param[in,out] rstr `CeedElemRestriction` to increment the reference counter 40834359f16Sjeremylt 40934359f16Sjeremylt @return An error code: 0 - success, otherwise - failure 41034359f16Sjeremylt 41134359f16Sjeremylt @ref Backend 41234359f16Sjeremylt **/ 4139560d06aSjeremylt int CeedElemRestrictionReference(CeedElemRestriction rstr) { 41434359f16Sjeremylt rstr->ref_count++; 41534359f16Sjeremylt return CEED_ERROR_SUCCESS; 41634359f16Sjeremylt } 41734359f16Sjeremylt 4186e15d496SJeremy L Thompson /** 419ca94c3ddSJeremy L Thompson @brief Estimate number of FLOPs required to apply `CeedElemRestriction` in `t_mode` 4206e15d496SJeremy L Thompson 421ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` to estimate FLOPs for 422ea61e9acSJeremy L Thompson @param[in] t_mode Apply restriction or transpose 423ea61e9acSJeremy L Thompson @param[out] flops Address of variable to hold FLOPs estimate 4246e15d496SJeremy L Thompson 4256e15d496SJeremy L Thompson @ref Backend 4266e15d496SJeremy L Thompson **/ 4272b730f8bSJeremy L Thompson int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedSize *flops) { 428e7f679fcSJeremy L Thompson CeedInt e_size = rstr->num_block * rstr->block_size * rstr->elem_size * rstr->num_comp, scale = 0; 42989edb9e3SSebastian Grimberg CeedRestrictionType rstr_type; 4301c66c397SJeremy L Thompson 43189edb9e3SSebastian Grimberg CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type)); 4323ac8f562SJeremy L Thompson if (rstr_type == CEED_RESTRICTION_POINTS) e_size = rstr->num_points * rstr->num_comp; 43377d1c127SSebastian Grimberg if (t_mode == CEED_TRANSPOSE) { 43489edb9e3SSebastian Grimberg switch (rstr_type) { 4353ac8f562SJeremy L Thompson case CEED_RESTRICTION_POINTS: 4363ac8f562SJeremy L Thompson scale = 0; 4373ac8f562SJeremy L Thompson break; 43889edb9e3SSebastian Grimberg case CEED_RESTRICTION_STRIDED: 43989edb9e3SSebastian Grimberg case CEED_RESTRICTION_STANDARD: 44077d1c127SSebastian Grimberg scale = 1; 44189edb9e3SSebastian Grimberg break; 44289edb9e3SSebastian Grimberg case CEED_RESTRICTION_ORIENTED: 44377d1c127SSebastian Grimberg scale = 2; 44489edb9e3SSebastian Grimberg break; 44589edb9e3SSebastian Grimberg case CEED_RESTRICTION_CURL_ORIENTED: 44677d1c127SSebastian Grimberg scale = 6; 44789edb9e3SSebastian Grimberg break; 4486e15d496SJeremy L Thompson } 44977d1c127SSebastian Grimberg } else { 45089edb9e3SSebastian Grimberg switch (rstr_type) { 45189edb9e3SSebastian Grimberg case CEED_RESTRICTION_STRIDED: 45289edb9e3SSebastian Grimberg case CEED_RESTRICTION_STANDARD: 4533ac8f562SJeremy L Thompson case CEED_RESTRICTION_POINTS: 45477d1c127SSebastian Grimberg scale = 0; 45589edb9e3SSebastian Grimberg break; 45689edb9e3SSebastian Grimberg case CEED_RESTRICTION_ORIENTED: 45777d1c127SSebastian Grimberg scale = 1; 45889edb9e3SSebastian Grimberg break; 45989edb9e3SSebastian Grimberg case CEED_RESTRICTION_CURL_ORIENTED: 46077d1c127SSebastian Grimberg scale = 5; 46189edb9e3SSebastian Grimberg break; 46277d1c127SSebastian Grimberg } 46377d1c127SSebastian Grimberg } 4646e15d496SJeremy L Thompson *flops = e_size * scale; 4656e15d496SJeremy L Thompson return CEED_ERROR_SUCCESS; 4666e15d496SJeremy L Thompson } 4676e15d496SJeremy L Thompson 4687a982d89SJeremy L. Thompson /// @} 4697a982d89SJeremy L. Thompson 47015910d16Sjeremylt /// @cond DOXYGEN_SKIP 47115910d16Sjeremylt static struct CeedElemRestriction_private ceed_elemrestriction_none; 47215910d16Sjeremylt /// @endcond 47315910d16Sjeremylt 4747a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 4757a982d89SJeremy L. Thompson /// CeedElemRestriction Public API 4767a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 4777a982d89SJeremy L. Thompson /// @addtogroup CeedElemRestrictionUser 478d7b241e6Sjeremylt /// @{ 479d7b241e6Sjeremylt 4807a982d89SJeremy L. Thompson /// Indicate that the stride is determined by the backend 48145f1e315Sjeremylt const CeedInt CEED_STRIDES_BACKEND[3] = {0}; 4827a982d89SJeremy L. Thompson 483ca94c3ddSJeremy L Thompson /// Argument for @ref CeedOperatorSetField() indicating that the field does not require a `CeedElemRestriction` 4842b730f8bSJeremy L Thompson const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = &ceed_elemrestriction_none; 4857a982d89SJeremy L. Thompson 486d7b241e6Sjeremylt /** 487ca94c3ddSJeremy L Thompson @brief Create a `CeedElemRestriction` 488d7b241e6Sjeremylt 489ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 490ca94c3ddSJeremy L Thompson @param[in] num_elem Number of elements described in the `offsets` array 491ea61e9acSJeremy L Thompson @param[in] elem_size Size (number of "nodes") per element 492ea61e9acSJeremy L Thompson @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 493fcbe8c06SSebastian Grimberg @param[in] comp_stride Stride between components for the same L-vector "node". 494ca94c3ddSJeremy L Thompson Data for node `i`, component `j`, element `k` can be found in the L-vector at index `offsets[i + k*elem_size] + j*comp_stride`. 495fcbe8c06SSebastian Grimberg @param[in] l_size The size of the L-vector. 496fcbe8c06SSebastian Grimberg This vector may be larger than the elements and fields given by this restriction. 497ca94c3ddSJeremy L Thompson @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 498ca94c3ddSJeremy L Thompson @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 499ca94c3ddSJeremy L Thompson @param[in] offsets Array of shape `[num_elem, elem_size]`. 500ca94c3ddSJeremy L Thompson Row `i` holds the ordered list of the offsets (into the input `CeedVector`) for the unknowns corresponding to element `i`, where 0 <= i < @a num_elem. 501ca94c3ddSJeremy L Thompson All offsets must be in the range `[0, l_size - 1]`. 502ca94c3ddSJeremy L Thompson @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 503d7b241e6Sjeremylt 504b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 505dfdf5a53Sjeremylt 5067a982d89SJeremy L. Thompson @ref User 507b11c1e72Sjeremylt **/ 5082b730f8bSJeremy L Thompson int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size, 5092b730f8bSJeremy L Thompson CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) { 5105fe0d4faSjeremylt if (!ceed->ElemRestrictionCreate) { 5115fe0d4faSjeremylt Ceed delegate; 5126574a04fSJeremy L Thompson 5132b730f8bSJeremy L Thompson CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 514ca94c3ddSJeremy L Thompson CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreate"); 5152b730f8bSJeremy L Thompson CeedCall(CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr)); 516e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5175fe0d4faSjeremylt } 5185fe0d4faSjeremylt 519e7f679fcSJeremy L Thompson CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 5206574a04fSJeremy L Thompson CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 521ca94c3ddSJeremy L Thompson CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 522ca94c3ddSJeremy L Thompson CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1"); 523e022e1f8SJeremy L Thompson 5242b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, rstr)); 525db002c03SJeremy L Thompson CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 526d1d35e2fSjeremylt (*rstr)->ref_count = 1; 527d1d35e2fSjeremylt (*rstr)->num_elem = num_elem; 528d1d35e2fSjeremylt (*rstr)->elem_size = elem_size; 529d1d35e2fSjeremylt (*rstr)->num_comp = num_comp; 530d1d35e2fSjeremylt (*rstr)->comp_stride = comp_stride; 531d1d35e2fSjeremylt (*rstr)->l_size = l_size; 53205fa913cSJeremy L Thompson (*rstr)->e_size = num_elem * elem_size * num_comp; 533e7f679fcSJeremy L Thompson (*rstr)->num_block = num_elem; 534e7f679fcSJeremy L Thompson (*rstr)->block_size = 1; 53561a27d74SSebastian Grimberg (*rstr)->rstr_type = CEED_RESTRICTION_STANDARD; 536fcbe8c06SSebastian Grimberg CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, NULL, *rstr)); 537e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 538d7b241e6Sjeremylt } 539d7b241e6Sjeremylt 540d7b241e6Sjeremylt /** 541ca94c3ddSJeremy L Thompson @brief Create a `CeedElemRestriction` with orientation signs 542fc0567d9Srezgarshakeri 543ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 544ca94c3ddSJeremy L Thompson @param[in] num_elem Number of elements described in the `offsets` array 545ea61e9acSJeremy L Thompson @param[in] elem_size Size (number of "nodes") per element 546ea61e9acSJeremy L Thompson @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 547fcbe8c06SSebastian Grimberg @param[in] comp_stride Stride between components for the same L-vector "node". 548ca94c3ddSJeremy L Thompson Data for node `i`, component `j`, element `k` can be found in the L-vector at index `offsets[i + k*elem_size] + j*comp_stride`. 549fcbe8c06SSebastian Grimberg @param[in] l_size The size of the L-vector. 550fcbe8c06SSebastian Grimberg This vector may be larger than the elements and fields given by this restriction. 551ca94c3ddSJeremy L Thompson @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 552ca94c3ddSJeremy L Thompson @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 553ca94c3ddSJeremy L Thompson @param[in] offsets Array of shape `[num_elem, elem_size]`. 554ca94c3ddSJeremy L Thompson Row i holds the ordered list of the offsets (into the input `CeedVector`) for the unknowns corresponding to element `i`, where `0 <= i < num_elem`. 555ca94c3ddSJeremy L Thompson All offsets must be in the range `[0, l_size - 1]`. 556ca94c3ddSJeremy L Thompson @param[in] orients Boolean array of shape `[num_elem, elem_size]` with `false` for positively oriented and `true` to flip the orientation 557ca94c3ddSJeremy L Thompson @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 558fc0567d9Srezgarshakeri 559fc0567d9Srezgarshakeri @return An error code: 0 - success, otherwise - failure 560fc0567d9Srezgarshakeri 561fc0567d9Srezgarshakeri @ref User 562fc0567d9Srezgarshakeri **/ 5632b730f8bSJeremy L Thompson int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size, 56477d1c127SSebastian Grimberg CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orients, 565fc0567d9Srezgarshakeri CeedElemRestriction *rstr) { 566fcbe8c06SSebastian Grimberg if (!ceed->ElemRestrictionCreate) { 567fc0567d9Srezgarshakeri Ceed delegate; 5686574a04fSJeremy L Thompson 5692b730f8bSJeremy L Thompson CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 570ca94c3ddSJeremy L Thompson CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateOriented"); 5712b730f8bSJeremy L Thompson CeedCall( 57277d1c127SSebastian Grimberg CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, orients, rstr)); 573fc0567d9Srezgarshakeri return CEED_ERROR_SUCCESS; 574fc0567d9Srezgarshakeri } 575fc0567d9Srezgarshakeri 576e7f679fcSJeremy L Thompson CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 5776574a04fSJeremy L Thompson CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 578ca94c3ddSJeremy L Thompson CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 579ca94c3ddSJeremy L Thompson CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1"); 580e022e1f8SJeremy L Thompson 5812b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, rstr)); 582db002c03SJeremy L Thompson CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 583fc0567d9Srezgarshakeri (*rstr)->ref_count = 1; 584fc0567d9Srezgarshakeri (*rstr)->num_elem = num_elem; 585fc0567d9Srezgarshakeri (*rstr)->elem_size = elem_size; 586fc0567d9Srezgarshakeri (*rstr)->num_comp = num_comp; 587fc0567d9Srezgarshakeri (*rstr)->comp_stride = comp_stride; 588fc0567d9Srezgarshakeri (*rstr)->l_size = l_size; 58905fa913cSJeremy L Thompson (*rstr)->e_size = num_elem * elem_size * num_comp; 590e7f679fcSJeremy L Thompson (*rstr)->num_block = num_elem; 591e7f679fcSJeremy L Thompson (*rstr)->block_size = 1; 592fcbe8c06SSebastian Grimberg (*rstr)->rstr_type = CEED_RESTRICTION_ORIENTED; 593fcbe8c06SSebastian Grimberg CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, orients, NULL, *rstr)); 59477d1c127SSebastian Grimberg return CEED_ERROR_SUCCESS; 59577d1c127SSebastian Grimberg } 59677d1c127SSebastian Grimberg 59777d1c127SSebastian Grimberg /** 598ca94c3ddSJeremy L Thompson @brief Create a `CeedElemRestriction` with a general tridiagonal transformation matrix for curl-conforming elements 59977d1c127SSebastian Grimberg 600ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 601ca94c3ddSJeremy L Thompson @param[in] num_elem Number of elements described in the `offsets` array 60277d1c127SSebastian Grimberg @param[in] elem_size Size (number of "nodes") per element 60377d1c127SSebastian Grimberg @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 604fcbe8c06SSebastian Grimberg @param[in] comp_stride Stride between components for the same L-vector "node". 605ca94c3ddSJeremy L Thompson Data for node `i`, component `j`, element `k` can be found in the L-vector at index `offsets[i + k*elem_size] + j*comp_stride`. 606fcbe8c06SSebastian Grimberg @param[in] l_size The size of the L-vector. 607fcbe8c06SSebastian Grimberg This vector may be larger than the elements and fields given by this restriction. 608ca94c3ddSJeremy L Thompson @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 609ca94c3ddSJeremy L Thompson @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 610ca94c3ddSJeremy L Thompson @param[in] offsets Array of shape `[num_elem, elem_size]`. 611ca94c3ddSJeremy L Thompson Row `i` holds the ordered list of the offsets (into the input `CeedVector`) for the unknowns corresponding to element `i`, where `0 <= i < num_elem`. 612ca94c3ddSJeremy L Thompson All offsets must be in the range `[0, l_size - 1]`. 613ca94c3ddSJeremy L Thompson @param[in] curl_orients Array of shape `[num_elem, 3 * elem_size]` representing a row-major tridiagonal matrix (`curl_orients[i * 3 * elem_size] = curl_orients[(i + 1) * 3 * elem_size - 1] = 0`, where `0 <= i < num_elem`) which is applied to the element unknowns upon restriction. 614ca94c3ddSJeremy L Thompson This orientation matrix allows for pairs of face degrees of freedom on elements for \f$H(\mathrm{curl})\f$ spaces to be coupled in the element restriction operation, which is a way to resolve face orientation issues for 3D meshes (https://dl.acm.org/doi/pdf/10.1145/3524456). 615ca94c3ddSJeremy L Thompson @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 61677d1c127SSebastian Grimberg 61777d1c127SSebastian Grimberg @return An error code: 0 - success, otherwise - failure 61877d1c127SSebastian Grimberg 61977d1c127SSebastian Grimberg @ref User 62077d1c127SSebastian Grimberg **/ 62177d1c127SSebastian Grimberg int CeedElemRestrictionCreateCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size, 6220c73c039SSebastian Grimberg CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const CeedInt8 *curl_orients, 62377d1c127SSebastian Grimberg CeedElemRestriction *rstr) { 624fcbe8c06SSebastian Grimberg if (!ceed->ElemRestrictionCreate) { 62577d1c127SSebastian Grimberg Ceed delegate; 62677d1c127SSebastian Grimberg 62777d1c127SSebastian Grimberg CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 628ca94c3ddSJeremy L Thompson CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateCurlOriented"); 62977d1c127SSebastian Grimberg CeedCall(CeedElemRestrictionCreateCurlOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, 63077d1c127SSebastian Grimberg curl_orients, rstr)); 63177d1c127SSebastian Grimberg return CEED_ERROR_SUCCESS; 63277d1c127SSebastian Grimberg } 63377d1c127SSebastian Grimberg 634e7f679fcSJeremy L Thompson CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 63577d1c127SSebastian Grimberg CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 636ca94c3ddSJeremy L Thompson CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 637ca94c3ddSJeremy L Thompson CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1"); 63877d1c127SSebastian Grimberg 63977d1c127SSebastian Grimberg CeedCall(CeedCalloc(1, rstr)); 640fcbe8c06SSebastian Grimberg CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 64177d1c127SSebastian Grimberg (*rstr)->ref_count = 1; 64277d1c127SSebastian Grimberg (*rstr)->num_elem = num_elem; 64377d1c127SSebastian Grimberg (*rstr)->elem_size = elem_size; 64477d1c127SSebastian Grimberg (*rstr)->num_comp = num_comp; 64577d1c127SSebastian Grimberg (*rstr)->comp_stride = comp_stride; 64677d1c127SSebastian Grimberg (*rstr)->l_size = l_size; 64705fa913cSJeremy L Thompson (*rstr)->e_size = num_elem * elem_size * num_comp; 648e7f679fcSJeremy L Thompson (*rstr)->num_block = num_elem; 649e7f679fcSJeremy L Thompson (*rstr)->block_size = 1; 650fcbe8c06SSebastian Grimberg (*rstr)->rstr_type = CEED_RESTRICTION_CURL_ORIENTED; 651fcbe8c06SSebastian Grimberg CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, curl_orients, *rstr)); 652fc0567d9Srezgarshakeri return CEED_ERROR_SUCCESS; 653fc0567d9Srezgarshakeri } 654fc0567d9Srezgarshakeri 655fc0567d9Srezgarshakeri /** 656ca94c3ddSJeremy L Thompson @brief Create a strided `CeedElemRestriction` 657d7b241e6Sjeremylt 658ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 659ea61e9acSJeremy L Thompson @param[in] num_elem Number of elements described by the restriction 660ea61e9acSJeremy L Thompson @param[in] elem_size Size (number of "nodes") per element 661ea61e9acSJeremy L Thompson @param[in] num_comp Number of field components per interpolation "node" (1 for scalar fields) 662fcbe8c06SSebastian Grimberg @param[in] l_size The size of the L-vector. 663fcbe8c06SSebastian Grimberg This vector may be larger than the elements and fields given by this restriction. 664ca94c3ddSJeremy L Thompson @param[in] strides Array for strides between `[nodes, components, elements]`. 665ca94c3ddSJeremy L Thompson Data for node `i`, component `j`, element `k` can be found in the L-vector at index `i*strides[0] + j*strides[1] + k*strides[2]`. 666ca94c3ddSJeremy L Thompson @ref CEED_STRIDES_BACKEND may be used for `CeedVector` ordered by the same `Ceed` backend. 667*972f909dSJeremy L Thompson `CEED_STRIDES_BACKEND` should only be used pass data between `CeedOperator` created with the same `Ceed` backend. 668*972f909dSJeremy L Thompson The L-vector layout will, in general, be different between `Ceed` backends. 669ca94c3ddSJeremy L Thompson @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 670d7b241e6Sjeremylt 671b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 672dfdf5a53Sjeremylt 6737a982d89SJeremy L. Thompson @ref User 674b11c1e72Sjeremylt **/ 6752b730f8bSJeremy L Thompson int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedSize l_size, const CeedInt strides[3], 676f90c8643Sjeremylt CeedElemRestriction *rstr) { 6775fe0d4faSjeremylt if (!ceed->ElemRestrictionCreate) { 6785fe0d4faSjeremylt Ceed delegate; 679b04eb3d9SSebastian Grimberg 6802b730f8bSJeremy L Thompson CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 681ca94c3ddSJeremy L Thompson CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateStrided"); 6822b730f8bSJeremy L Thompson CeedCall(CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, l_size, strides, rstr)); 683e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6845fe0d4faSjeremylt } 6855fe0d4faSjeremylt 686e7f679fcSJeremy L Thompson CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 6876574a04fSJeremy L Thompson CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 688ca94c3ddSJeremy L Thompson CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 689e7f679fcSJeremy 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"); 690e022e1f8SJeremy L Thompson 6912b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, rstr)); 692db002c03SJeremy L Thompson CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 693d1d35e2fSjeremylt (*rstr)->ref_count = 1; 694d1d35e2fSjeremylt (*rstr)->num_elem = num_elem; 695d1d35e2fSjeremylt (*rstr)->elem_size = elem_size; 696d1d35e2fSjeremylt (*rstr)->num_comp = num_comp; 697d1d35e2fSjeremylt (*rstr)->l_size = l_size; 69805fa913cSJeremy L Thompson (*rstr)->e_size = num_elem * elem_size * num_comp; 699e7f679fcSJeremy L Thompson (*rstr)->num_block = num_elem; 700e7f679fcSJeremy L Thompson (*rstr)->block_size = 1; 701fcbe8c06SSebastian Grimberg (*rstr)->rstr_type = CEED_RESTRICTION_STRIDED; 7022b730f8bSJeremy L Thompson CeedCall(CeedMalloc(3, &(*rstr)->strides)); 7032b730f8bSJeremy L Thompson for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i]; 704fcbe8c06SSebastian Grimberg CeedCall(ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr)); 705e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 706d7b241e6Sjeremylt } 707d7b241e6Sjeremylt 708d7b241e6Sjeremylt /** 709ca94c3ddSJeremy L Thompson @brief Create a points `CeedElemRestriction`, for restricting for restricting from a all local points to the current element in which they are located. 7103ac8f562SJeremy L Thompson 7113ac8f562SJeremy L Thompson The offsets array is arranged as 7123ac8f562SJeremy L Thompson 7133ac8f562SJeremy L Thompson element_0_start_index 7143ac8f562SJeremy L Thompson element_1_start_index 7153ac8f562SJeremy L Thompson ... 7163ac8f562SJeremy L Thompson element_n_start_index 7173ac8f562SJeremy L Thompson element_n_stop_index 7183ac8f562SJeremy L Thompson element_0_point_0 7193ac8f562SJeremy L Thompson element_0_point_1 7203ac8f562SJeremy L Thompson ... 7213ac8f562SJeremy L Thompson 722ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 723ca94c3ddSJeremy L Thompson @param[in] num_elem Number of elements described in the `offsets` array 724ca94c3ddSJeremy L Thompson @param[in] num_points Number of points described in the `offsets` array 7253ac8f562SJeremy L Thompson @param[in] num_comp Number of field components per interpolation node (1 for scalar fields). 7263ac8f562SJeremy L Thompson Components are assumed to be contiguous by point. 7273ac8f562SJeremy L Thompson @param[in] l_size The size of the L-vector. 7283ac8f562SJeremy L Thompson This vector may be larger than the elements and fields given by this restriction. 729ca94c3ddSJeremy L Thompson @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 730ca94c3ddSJeremy L Thompson @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 731ca94c3ddSJeremy L Thompson @param[in] offsets Array of size `num_elem + 1 + num_points`. 7323ac8f562SJeremy L Thompson The first portion of the offsets array holds the ranges of indices corresponding to each element. 7333ac8f562SJeremy L Thompson The second portion holds the indices for each element. 734ca94c3ddSJeremy L Thompson @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 7353ac8f562SJeremy L Thompson 7363ac8f562SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 7373ac8f562SJeremy L Thompson 7383ac8f562SJeremy L Thompson @ref Backend 7393ac8f562SJeremy L Thompson **/ 7403ac8f562SJeremy L Thompson int CeedElemRestrictionCreateAtPoints(Ceed ceed, CeedInt num_elem, CeedInt num_points, CeedInt num_comp, CeedSize l_size, CeedMemType mem_type, 7413ac8f562SJeremy L Thompson CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) { 7423ac8f562SJeremy L Thompson if (!ceed->ElemRestrictionCreateAtPoints) { 7433ac8f562SJeremy L Thompson Ceed delegate; 7443ac8f562SJeremy L Thompson 7453ac8f562SJeremy L Thompson CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 746ca94c3ddSJeremy L Thompson CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateAtPoints"); 7473ac8f562SJeremy L Thompson CeedCall(CeedElemRestrictionCreateAtPoints(delegate, num_elem, num_points, num_comp, l_size, mem_type, copy_mode, offsets, rstr)); 7483ac8f562SJeremy L Thompson return CEED_ERROR_SUCCESS; 7493ac8f562SJeremy L Thompson } 7503ac8f562SJeremy L Thompson 7513ac8f562SJeremy L Thompson CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 7523ac8f562SJeremy L Thompson CeedCheck(num_points >= 0, ceed, CEED_ERROR_DIMENSION, "Number of points must be non-negative"); 753ca94c3ddSJeremy L Thompson CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 7543ac8f562SJeremy L Thompson CeedCheck(l_size >= num_points * num_comp, ceed, CEED_ERROR_DIMENSION, "L-vector must be at least num_points * num_comp"); 7553ac8f562SJeremy L Thompson 7563ac8f562SJeremy L Thompson CeedCall(CeedCalloc(1, rstr)); 7573ac8f562SJeremy L Thompson CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 7583ac8f562SJeremy L Thompson (*rstr)->ref_count = 1; 7593ac8f562SJeremy L Thompson (*rstr)->num_elem = num_elem; 7603ac8f562SJeremy L Thompson (*rstr)->num_points = num_points; 7613ac8f562SJeremy L Thompson (*rstr)->num_comp = num_comp; 7623ac8f562SJeremy L Thompson (*rstr)->l_size = l_size; 76305fa913cSJeremy L Thompson (*rstr)->e_size = num_points * num_comp; 76405fa913cSJeremy L Thompson (*rstr)->num_block = num_elem; 7653ac8f562SJeremy L Thompson (*rstr)->block_size = 1; 7663ac8f562SJeremy L Thompson (*rstr)->rstr_type = CEED_RESTRICTION_POINTS; 7673ac8f562SJeremy L Thompson CeedCall(ceed->ElemRestrictionCreateAtPoints(mem_type, copy_mode, offsets, NULL, NULL, *rstr)); 7683ac8f562SJeremy L Thompson return CEED_ERROR_SUCCESS; 7693ac8f562SJeremy L Thompson } 7703ac8f562SJeremy L Thompson 7713ac8f562SJeremy L Thompson /** 772ca94c3ddSJeremy L Thompson @brief Create a blocked `CeedElemRestriction`, typically only used by backends 773d7b241e6Sjeremylt 774ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 775ca94c3ddSJeremy L Thompson @param[in] num_elem Number of elements described in the `offsets` array 776ea61e9acSJeremy L Thompson @param[in] elem_size Size (number of unknowns) per element 777e7f679fcSJeremy L Thompson @param[in] block_size Number of elements in a block 778ea61e9acSJeremy L Thompson @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 779fcbe8c06SSebastian Grimberg @param[in] comp_stride Stride between components for the same L-vector "node". 780ca94c3ddSJeremy L Thompson Data for node `i`, component `j`, element `k` can be found in the L-vector at index `offsets[i + k*elem_size] + j*comp_stride`. 781fcbe8c06SSebastian Grimberg @param[in] l_size The size of the L-vector. 782fcbe8c06SSebastian Grimberg This vector may be larger than the elements and fields given by this restriction. 783ca94c3ddSJeremy L Thompson @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 784ca94c3ddSJeremy L Thompson @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 785ca94c3ddSJeremy L Thompson @param[in] offsets Array of shape `[num_elem, elem_size]`. 786ca94c3ddSJeremy L Thompson Row `i` holds the ordered list of the offsets (into the input `CeedVector`) for the unknowns corresponding to element `i`, where `0 <= i < num_elem`. 787ca94c3ddSJeremy L Thompson All offsets must be in the range `[0, l_size - 1]`. 788ca94c3ddSJeremy L Thompson The backend will permute and pad this array to the desired ordering for the blocksize, which is typically given by the backend. 789ca94c3ddSJeremy L Thompson The default reordering is to interlace elements. 790ca94c3ddSJeremy L Thompson @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 791d7b241e6Sjeremylt 792b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 793dfdf5a53Sjeremylt 7947a982d89SJeremy L. Thompson @ref Backend 795b11c1e72Sjeremylt **/ 796e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedInt comp_stride, 7972b730f8bSJeremy L Thompson CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, 7984ce2993fSjeremylt CeedElemRestriction *rstr) { 7991c66c397SJeremy L Thompson CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size); 800d7b241e6Sjeremylt 8015fe0d4faSjeremylt if (!ceed->ElemRestrictionCreateBlocked) { 8025fe0d4faSjeremylt Ceed delegate; 8036574a04fSJeremy L Thompson 8042b730f8bSJeremy L Thompson CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 805ca94c3ddSJeremy L Thompson CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlocked"); 806e7f679fcSJeremy L Thompson CeedCall(CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, 807e7f679fcSJeremy L Thompson rstr)); 808e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8095fe0d4faSjeremylt } 810d7b241e6Sjeremylt 811e7f679fcSJeremy L Thompson CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 8126574a04fSJeremy L Thompson CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 813e7f679fcSJeremy L Thompson CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1"); 814ca94c3ddSJeremy L Thompson CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 815ca94c3ddSJeremy L Thompson CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1"); 816e022e1f8SJeremy L Thompson 817e7f679fcSJeremy L Thompson CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets)); 818e7f679fcSJeremy L Thompson CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size)); 819d7b241e6Sjeremylt 820db002c03SJeremy L Thompson CeedCall(CeedCalloc(1, rstr)); 821db002c03SJeremy L Thompson CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 822d1d35e2fSjeremylt (*rstr)->ref_count = 1; 823d1d35e2fSjeremylt (*rstr)->num_elem = num_elem; 824d1d35e2fSjeremylt (*rstr)->elem_size = elem_size; 825d1d35e2fSjeremylt (*rstr)->num_comp = num_comp; 826d1d35e2fSjeremylt (*rstr)->comp_stride = comp_stride; 827d1d35e2fSjeremylt (*rstr)->l_size = l_size; 82805fa913cSJeremy L Thompson (*rstr)->e_size = num_block * block_size * elem_size * num_comp; 829e7f679fcSJeremy L Thompson (*rstr)->num_block = num_block; 830e7f679fcSJeremy L Thompson (*rstr)->block_size = block_size; 83161a27d74SSebastian Grimberg (*rstr)->rstr_type = CEED_RESTRICTION_STANDARD; 832e7f679fcSJeremy L Thompson CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL, NULL, *rstr)); 8331c66c397SJeremy L Thompson if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets)); 834e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 835d7b241e6Sjeremylt } 836d7b241e6Sjeremylt 837b11c1e72Sjeremylt /** 838ca94c3ddSJeremy L Thompson @brief Create a blocked oriented `CeedElemRestriction`, typically only used by backends 83977d1c127SSebastian Grimberg 840ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 841ca94c3ddSJeremy L Thompson @param[in] num_elem Number of elements described in the `offsets` array. 84277d1c127SSebastian Grimberg @param[in] elem_size Size (number of unknowns) per element 843e7f679fcSJeremy L Thompson @param[in] block_size Number of elements in a block 84477d1c127SSebastian Grimberg @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 845fcbe8c06SSebastian Grimberg @param[in] comp_stride Stride between components for the same L-vector "node". 846ca94c3ddSJeremy L Thompson Data for node `i`, component `j`, element `k` can be found in the L-vector at index `offsets[i + k*elem_size] + j*comp_stride`. 847fcbe8c06SSebastian Grimberg @param[in] l_size The size of the L-vector. 848fcbe8c06SSebastian Grimberg This vector may be larger than the elements and fields given by this restriction. 849ca94c3ddSJeremy L Thompson @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 850ca94c3ddSJeremy L Thompson @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 851ca94c3ddSJeremy L Thompson @param[in] offsets Array of shape `[num_elem, elem_size]`. 852ca94c3ddSJeremy L Thompson Row `i` holds the ordered list of the offsets (into the input `CeedVector`) for the unknowns corresponding to element `i`, where `0 <= i < num_elem`. 853ca94c3ddSJeremy L Thompson All offsets must be in the range `[0, l_size - 1]`. 854ca94c3ddSJeremy L Thompson The backend will permute and pad this array to the desired ordering for the blocksize, which is typically given by the backend. 855ca94c3ddSJeremy L Thompson The default reordering is to interlace elements. 856ca94c3ddSJeremy L Thompson @param[in] orients Boolean array of shape `[num_elem, elem_size]` with `false` for positively oriented and `true` to flip the orientation. 857ca94c3ddSJeremy L Thompson Will also be permuted and padded similarly to `offsets`. 858ca94c3ddSJeremy L Thompson @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 85977d1c127SSebastian Grimberg 86077d1c127SSebastian Grimberg @return An error code: 0 - success, otherwise - failure 86177d1c127SSebastian Grimberg 86277d1c127SSebastian Grimberg @ref Backend 86377d1c127SSebastian Grimberg **/ 864e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, 865e7f679fcSJeremy L Thompson CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, 866e7f679fcSJeremy L Thompson const CeedInt *offsets, const bool *orients, CeedElemRestriction *rstr) { 867e7f679fcSJeremy L Thompson bool *block_orients; 8681c66c397SJeremy L Thompson CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size); 86977d1c127SSebastian Grimberg 870fcbe8c06SSebastian Grimberg if (!ceed->ElemRestrictionCreateBlocked) { 87177d1c127SSebastian Grimberg Ceed delegate; 87277d1c127SSebastian Grimberg 87377d1c127SSebastian Grimberg CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 874ca94c3ddSJeremy L Thompson CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedOriented"); 875e7f679fcSJeremy L Thompson CeedCall(CeedElemRestrictionCreateBlockedOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode, 87677d1c127SSebastian Grimberg offsets, orients, rstr)); 87777d1c127SSebastian Grimberg return CEED_ERROR_SUCCESS; 87877d1c127SSebastian Grimberg } 87977d1c127SSebastian Grimberg 88077d1c127SSebastian Grimberg CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 881e7f679fcSJeremy L Thompson CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1"); 882ca94c3ddSJeremy L Thompson CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 883ca94c3ddSJeremy L Thompson CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1"); 88477d1c127SSebastian Grimberg 885e7f679fcSJeremy L Thompson CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets)); 886e7f679fcSJeremy L Thompson CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_orients)); 887e7f679fcSJeremy L Thompson CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size)); 888e7f679fcSJeremy L Thompson CeedCall(CeedPermutePadOrients(orients, block_orients, num_block, num_elem, block_size, elem_size)); 88977d1c127SSebastian Grimberg 890fcbe8c06SSebastian Grimberg CeedCall(CeedCalloc(1, rstr)); 891fcbe8c06SSebastian Grimberg CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 89277d1c127SSebastian Grimberg (*rstr)->ref_count = 1; 89377d1c127SSebastian Grimberg (*rstr)->num_elem = num_elem; 89477d1c127SSebastian Grimberg (*rstr)->elem_size = elem_size; 89577d1c127SSebastian Grimberg (*rstr)->num_comp = num_comp; 89677d1c127SSebastian Grimberg (*rstr)->comp_stride = comp_stride; 89777d1c127SSebastian Grimberg (*rstr)->l_size = l_size; 89805fa913cSJeremy L Thompson (*rstr)->e_size = num_block * block_size * elem_size * num_comp; 899e7f679fcSJeremy L Thompson (*rstr)->num_block = num_block; 900e7f679fcSJeremy L Thompson (*rstr)->block_size = block_size; 901fcbe8c06SSebastian Grimberg (*rstr)->rstr_type = CEED_RESTRICTION_ORIENTED; 902e7f679fcSJeremy L Thompson CeedCall( 903e7f679fcSJeremy L Thompson ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, (const bool *)block_orients, NULL, *rstr)); 9041c66c397SJeremy L Thompson if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets)); 90577d1c127SSebastian Grimberg return CEED_ERROR_SUCCESS; 90677d1c127SSebastian Grimberg } 90777d1c127SSebastian Grimberg 90877d1c127SSebastian Grimberg /** 909ca94c3ddSJeremy L Thompson @brief Create a blocked curl-oriented `CeedElemRestriction`, typically only used by backends 91077d1c127SSebastian Grimberg 911ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 912ca94c3ddSJeremy L Thompson @param[in] num_elem Number of elements described in the `offsets` array. 91377d1c127SSebastian Grimberg @param[in] elem_size Size (number of unknowns) per element 914e7f679fcSJeremy L Thompson @param[in] block_size Number of elements in a block 91577d1c127SSebastian Grimberg @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 916fcbe8c06SSebastian Grimberg @param[in] comp_stride Stride between components for the same L-vector "node". 917ca94c3ddSJeremy L Thompson Data for node `i`, component `j`, element `k` can be found in the L-vector at index `offsets[i + k*elem_size] + j*comp_stride`. 918fcbe8c06SSebastian Grimberg @param[in] l_size The size of the L-vector. 919fcbe8c06SSebastian Grimberg This vector may be larger than the elements and fields given by this restriction. 920ca94c3ddSJeremy L Thompson @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 921ca94c3ddSJeremy L Thompson @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 922ca94c3ddSJeremy L Thompson @param[in] offsets Array of shape `[num_elem, elem_size]`. 923ca94c3ddSJeremy L Thompson Row `i` holds the ordered list of the offsets (into the input `CeedVector`) for the unknowns corresponding to element `i`, where `0 <= i < num_elem`. 924ca94c3ddSJeremy L Thompson All offsets must be in the range `[0, l_size - 1]`. 925ca94c3ddSJeremy L Thompson The backend will permute and pad this array to the desired ordering for the blocksize, which is typically given by the backend. 926ca94c3ddSJeremy L Thompson The default reordering is to interlace elements. 927ca94c3ddSJeremy L Thompson @param[in] curl_orients Array of shape `[num_elem, 3 * elem_size]` representing a row-major tridiagonal matrix (`curl_orients[i * 3 * elem_size] = curl_orients[(i + 1) * 3 * elem_size - 1] = 0`, where `0 <= i < num_elem`) which is applied to the element unknowns upon restriction. 928ca94c3ddSJeremy L Thompson This orientation matrix allows for pairs of face degrees of freedom on elements for \f$H(\mathrm{curl})\f$ spaces to be coupled in the element restriction operation, which is a way to resolve face orientation issues for 3D meshes (https://dl.acm.org/doi/pdf/10.1145/3524456). 929ca94c3ddSJeremy L Thompson Will also be permuted and padded similarly to offsets. 930ca94c3ddSJeremy L Thompson @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 93177d1c127SSebastian Grimberg 93277d1c127SSebastian Grimberg @return An error code: 0 - success, otherwise - failure 93377d1c127SSebastian Grimberg 93477d1c127SSebastian Grimberg @ref Backend 93577d1c127SSebastian Grimberg **/ 936e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, 93777d1c127SSebastian Grimberg CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, 9380c73c039SSebastian Grimberg const CeedInt *offsets, const CeedInt8 *curl_orients, CeedElemRestriction *rstr) { 939e7f679fcSJeremy L Thompson CeedInt8 *block_curl_orients; 9401c66c397SJeremy L Thompson CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size); 94177d1c127SSebastian Grimberg 942fcbe8c06SSebastian Grimberg if (!ceed->ElemRestrictionCreateBlocked) { 94377d1c127SSebastian Grimberg Ceed delegate; 94477d1c127SSebastian Grimberg 94577d1c127SSebastian Grimberg CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 946ca94c3ddSJeremy L Thompson CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedCurlOriented"); 947e7f679fcSJeremy L Thompson CeedCall(CeedElemRestrictionCreateBlockedCurlOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, 948e7f679fcSJeremy L Thompson copy_mode, offsets, curl_orients, rstr)); 94977d1c127SSebastian Grimberg return CEED_ERROR_SUCCESS; 95077d1c127SSebastian Grimberg } 95177d1c127SSebastian Grimberg 952e7f679fcSJeremy L Thompson CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 95377d1c127SSebastian Grimberg CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 954e7f679fcSJeremy L Thompson CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1"); 955ca94c3ddSJeremy L Thompson CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 956ca94c3ddSJeremy L Thompson CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1"); 95777d1c127SSebastian Grimberg 958e7f679fcSJeremy L Thompson CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets)); 959e7f679fcSJeremy L Thompson CeedCall(CeedCalloc(num_block * block_size * 3 * elem_size, &block_curl_orients)); 960e7f679fcSJeremy L Thompson CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size)); 961e7f679fcSJeremy L Thompson CeedCall(CeedPermutePadCurlOrients(curl_orients, block_curl_orients, num_block, num_elem, block_size, 3 * elem_size)); 96277d1c127SSebastian Grimberg 963fcbe8c06SSebastian Grimberg CeedCall(CeedCalloc(1, rstr)); 964fcbe8c06SSebastian Grimberg CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 96577d1c127SSebastian Grimberg (*rstr)->ref_count = 1; 96677d1c127SSebastian Grimberg (*rstr)->num_elem = num_elem; 96777d1c127SSebastian Grimberg (*rstr)->elem_size = elem_size; 96877d1c127SSebastian Grimberg (*rstr)->num_comp = num_comp; 96977d1c127SSebastian Grimberg (*rstr)->comp_stride = comp_stride; 97077d1c127SSebastian Grimberg (*rstr)->l_size = l_size; 97105fa913cSJeremy L Thompson (*rstr)->e_size = num_block * block_size * elem_size * num_comp; 972e7f679fcSJeremy L Thompson (*rstr)->num_block = num_block; 973e7f679fcSJeremy L Thompson (*rstr)->block_size = block_size; 974fcbe8c06SSebastian Grimberg (*rstr)->rstr_type = CEED_RESTRICTION_CURL_ORIENTED; 975e7f679fcSJeremy L Thompson CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL, 976e7f679fcSJeremy L Thompson (const CeedInt8 *)block_curl_orients, *rstr)); 9771c66c397SJeremy L Thompson if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets)); 97877d1c127SSebastian Grimberg return CEED_ERROR_SUCCESS; 97977d1c127SSebastian Grimberg } 98077d1c127SSebastian Grimberg 98177d1c127SSebastian Grimberg /** 982ca94c3ddSJeremy L Thompson @brief Create a blocked strided `CeedElemRestriction`, typically only used by backends 9837509a596Sjeremylt 984ca94c3ddSJeremy L Thompson @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 985ea61e9acSJeremy L Thompson @param[in] num_elem Number of elements described by the restriction 986ea61e9acSJeremy L Thompson @param[in] elem_size Size (number of "nodes") per element 987e7f679fcSJeremy L Thompson @param[in] block_size Number of elements in a block 988ea61e9acSJeremy L Thompson @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 989fcbe8c06SSebastian Grimberg @param[in] l_size The size of the L-vector. 990fcbe8c06SSebastian Grimberg This vector may be larger than the elements and fields given by this restriction. 991ca94c3ddSJeremy L Thompson @param[in] strides Array for strides between `[nodes, components, elements]`. 992ca94c3ddSJeremy L Thompson Data for node `i`, component `j`, element `k` can be found in the L-vector at index `i*strides[0] + j*strides[1] +k*strides[2]`. 993ca94c3ddSJeremy L Thompson @ref CEED_STRIDES_BACKEND may be used for `CeedVector` ordered by the same `Ceed` backend. 994ca94c3ddSJeremy L Thompson @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 9957509a596Sjeremylt 9967509a596Sjeremylt @return An error code: 0 - success, otherwise - failure 9977509a596Sjeremylt 9987a982d89SJeremy L. Thompson @ref User 9997509a596Sjeremylt **/ 1000e7f679fcSJeremy L Thompson int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedSize l_size, 10018621c6c6SJeremy L Thompson const CeedInt strides[3], CeedElemRestriction *rstr) { 1002e7f679fcSJeremy L Thompson CeedInt num_block = (num_elem / block_size) + !!(num_elem % block_size); 10037509a596Sjeremylt 10047509a596Sjeremylt if (!ceed->ElemRestrictionCreateBlocked) { 10057509a596Sjeremylt Ceed delegate; 10066574a04fSJeremy L Thompson 10072b730f8bSJeremy L Thompson CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 1008ca94c3ddSJeremy L Thompson CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedStrided"); 1009e7f679fcSJeremy L Thompson CeedCall(CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, block_size, num_comp, l_size, strides, rstr)); 1010e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 10117509a596Sjeremylt } 10127509a596Sjeremylt 1013e7f679fcSJeremy L Thompson CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 10146574a04fSJeremy L Thompson CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 1015e7f679fcSJeremy L Thompson CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1"); 1016ca94c3ddSJeremy L Thompson CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 1017e7f679fcSJeremy 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"); 1018e022e1f8SJeremy L Thompson 10192b730f8bSJeremy L Thompson CeedCall(CeedCalloc(1, rstr)); 1020db002c03SJeremy L Thompson CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 1021d1d35e2fSjeremylt (*rstr)->ref_count = 1; 1022d1d35e2fSjeremylt (*rstr)->num_elem = num_elem; 1023d1d35e2fSjeremylt (*rstr)->elem_size = elem_size; 1024d1d35e2fSjeremylt (*rstr)->num_comp = num_comp; 1025d1d35e2fSjeremylt (*rstr)->l_size = l_size; 102605fa913cSJeremy L Thompson (*rstr)->e_size = num_block * block_size * elem_size * num_comp; 1027e7f679fcSJeremy L Thompson (*rstr)->num_block = num_block; 1028e7f679fcSJeremy L Thompson (*rstr)->block_size = block_size; 1029fcbe8c06SSebastian Grimberg (*rstr)->rstr_type = CEED_RESTRICTION_STRIDED; 10302b730f8bSJeremy L Thompson CeedCall(CeedMalloc(3, &(*rstr)->strides)); 10312b730f8bSJeremy L Thompson for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i]; 1032fcbe8c06SSebastian Grimberg CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr)); 1033e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 10347509a596Sjeremylt } 10357509a596Sjeremylt 10367509a596Sjeremylt /** 1037ca94c3ddSJeremy L Thompson @brief Copy the pointer to a `CeedElemRestriction` and set @ref CeedElemRestrictionApply() implementation to use the unsigned version. 1038c17ec2beSJeremy L Thompson 1039ca94c3ddSJeremy L Thompson Both pointers should be destroyed with @ref CeedElemRestrictionDestroy(). 1040c17ec2beSJeremy L Thompson 1041ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` to create unsigned reference to 1042ca94c3ddSJeremy L Thompson @param[in,out] rstr_unsigned Variable to store unsigned `CeedElemRestriction` 1043c17ec2beSJeremy L Thompson 1044c17ec2beSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1045c17ec2beSJeremy L Thompson 1046c17ec2beSJeremy L Thompson @ref User 1047c17ec2beSJeremy L Thompson **/ 1048c17ec2beSJeremy L Thompson int CeedElemRestrictionCreateUnsignedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unsigned) { 1049c17ec2beSJeremy L Thompson CeedCall(CeedCalloc(1, rstr_unsigned)); 1050c17ec2beSJeremy L Thompson 1051c17ec2beSJeremy L Thompson // Copy old rstr 1052c17ec2beSJeremy L Thompson memcpy(*rstr_unsigned, rstr, sizeof(struct CeedElemRestriction_private)); 1053c17ec2beSJeremy L Thompson (*rstr_unsigned)->ceed = NULL; 1054c17ec2beSJeremy L Thompson CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unsigned)->ceed)); 1055c17ec2beSJeremy L Thompson (*rstr_unsigned)->ref_count = 1; 1056c17ec2beSJeremy L Thompson (*rstr_unsigned)->strides = NULL; 1057c17ec2beSJeremy L Thompson if (rstr->strides) { 1058c17ec2beSJeremy L Thompson CeedCall(CeedMalloc(3, &(*rstr_unsigned)->strides)); 1059c17ec2beSJeremy L Thompson for (CeedInt i = 0; i < 3; i++) (*rstr_unsigned)->strides[i] = rstr->strides[i]; 1060c17ec2beSJeremy L Thompson } 10617c1dbaffSSebastian Grimberg CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unsigned)->rstr_base)); 1062c17ec2beSJeremy L Thompson 1063c17ec2beSJeremy L Thompson // Override Apply 1064c17ec2beSJeremy L Thompson (*rstr_unsigned)->Apply = rstr->ApplyUnsigned; 1065c17ec2beSJeremy L Thompson return CEED_ERROR_SUCCESS; 1066c17ec2beSJeremy L Thompson } 1067c17ec2beSJeremy L Thompson 1068c17ec2beSJeremy L Thompson /** 1069ca94c3ddSJeremy L Thompson @brief Copy the pointer to a `CeedElemRestriction` and set @ref CeedElemRestrictionApply() implementation to use the unoriented version. 10707c1dbaffSSebastian Grimberg 1071ca94c3ddSJeremy L Thompson Both pointers should be destroyed with @ref CeedElemRestrictionDestroy(). 10727c1dbaffSSebastian Grimberg 1073ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` to create unoriented reference to 1074ca94c3ddSJeremy L Thompson @param[in,out] rstr_unoriented Variable to store unoriented `CeedElemRestriction` 10757c1dbaffSSebastian Grimberg 10767c1dbaffSSebastian Grimberg @return An error code: 0 - success, otherwise - failure 10777c1dbaffSSebastian Grimberg 10787c1dbaffSSebastian Grimberg @ref User 10797c1dbaffSSebastian Grimberg **/ 10807c1dbaffSSebastian Grimberg int CeedElemRestrictionCreateUnorientedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unoriented) { 10817c1dbaffSSebastian Grimberg CeedCall(CeedCalloc(1, rstr_unoriented)); 10827c1dbaffSSebastian Grimberg 10837c1dbaffSSebastian Grimberg // Copy old rstr 10847c1dbaffSSebastian Grimberg memcpy(*rstr_unoriented, rstr, sizeof(struct CeedElemRestriction_private)); 10857c1dbaffSSebastian Grimberg (*rstr_unoriented)->ceed = NULL; 10867c1dbaffSSebastian Grimberg CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unoriented)->ceed)); 10877c1dbaffSSebastian Grimberg (*rstr_unoriented)->ref_count = 1; 10887c1dbaffSSebastian Grimberg (*rstr_unoriented)->strides = NULL; 10897c1dbaffSSebastian Grimberg if (rstr->strides) { 10907c1dbaffSSebastian Grimberg CeedCall(CeedMalloc(3, &(*rstr_unoriented)->strides)); 10917c1dbaffSSebastian Grimberg for (CeedInt i = 0; i < 3; i++) (*rstr_unoriented)->strides[i] = rstr->strides[i]; 10927c1dbaffSSebastian Grimberg } 10937c1dbaffSSebastian Grimberg CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unoriented)->rstr_base)); 10947c1dbaffSSebastian Grimberg 10957c1dbaffSSebastian Grimberg // Override Apply 10967c1dbaffSSebastian Grimberg (*rstr_unoriented)->Apply = rstr->ApplyUnoriented; 10977c1dbaffSSebastian Grimberg return CEED_ERROR_SUCCESS; 10987c1dbaffSSebastian Grimberg } 10997c1dbaffSSebastian Grimberg 11007c1dbaffSSebastian Grimberg /** 1101ca94c3ddSJeremy L Thompson @brief Copy the pointer to a `CeedElemRestriction`. 11029fd66db6SSebastian Grimberg 1103ca94c3ddSJeremy L Thompson Both pointers should be destroyed with @ref CeedElemRestrictionDestroy(). 11049560d06aSjeremylt 1105ca94c3ddSJeremy L Thompson 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`. 1106ca94c3ddSJeremy L Thompson This `CeedElemRestriction` will be destroyed if `*rstr_copy` is the only reference to this `CeedElemRestriction`. 1107ea61e9acSJeremy L Thompson 1108ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` to copy reference to 1109ea61e9acSJeremy L Thompson @param[in,out] rstr_copy Variable to store copied reference 11109560d06aSjeremylt 11119560d06aSjeremylt @return An error code: 0 - success, otherwise - failure 11129560d06aSjeremylt 11139560d06aSjeremylt @ref User 11149560d06aSjeremylt **/ 11152b730f8bSJeremy L Thompson int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_copy) { 1116393ac2cdSJeremy L Thompson if (rstr != CEED_ELEMRESTRICTION_NONE) CeedCall(CeedElemRestrictionReference(rstr)); 11172b730f8bSJeremy L Thompson CeedCall(CeedElemRestrictionDestroy(rstr_copy)); 11189560d06aSjeremylt *rstr_copy = rstr; 11199560d06aSjeremylt return CEED_ERROR_SUCCESS; 11209560d06aSjeremylt } 11219560d06aSjeremylt 11229560d06aSjeremylt /** 1123ca94c3ddSJeremy L Thompson @brief Create `CeedVector` associated with a `CeedElemRestriction` 1124b11c1e72Sjeremylt 1125ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 1126ca94c3ddSJeremy L Thompson @param[out] l_vec The address of the L-vector to be created, or `NULL` 1127ca94c3ddSJeremy L Thompson @param[out] e_vec The address of the E-vector to be created, or `NULL` 1128b11c1e72Sjeremylt 1129b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1130dfdf5a53Sjeremylt 11317a982d89SJeremy L. Thompson @ref User 1132b11c1e72Sjeremylt **/ 11332b730f8bSJeremy L Thompson int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, CeedVector *e_vec) { 1134d2643443SJeremy L Thompson CeedSize e_size, l_size; 113548acf710SJeremy L Thompson 1136d1d35e2fSjeremylt l_size = rstr->l_size; 113748acf710SJeremy L Thompson if (rstr->rstr_type == CEED_RESTRICTION_POINTS) { 113848acf710SJeremy L Thompson e_size = rstr->num_points * rstr->num_comp; 113948acf710SJeremy L Thompson } else { 1140e7f679fcSJeremy L Thompson e_size = rstr->num_block * rstr->block_size * rstr->elem_size * rstr->num_comp; 114148acf710SJeremy L Thompson } 11422b730f8bSJeremy L Thompson if (l_vec) CeedCall(CeedVectorCreate(rstr->ceed, l_size, l_vec)); 11432b730f8bSJeremy L Thompson if (e_vec) CeedCall(CeedVectorCreate(rstr->ceed, e_size, e_vec)); 1144e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1145d7b241e6Sjeremylt } 1146d7b241e6Sjeremylt 1147d7b241e6Sjeremylt /** 1148d9e1f99aSValeria Barra @brief Restrict an L-vector to an E-vector or apply its transpose 1149d7b241e6Sjeremylt 1150ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 1151ea61e9acSJeremy L Thompson @param[in] t_mode Apply restriction or transpose 1152ca94c3ddSJeremy L Thompson @param[in] u Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE) 1153ca94c3ddSJeremy L Thompson @param[out] ru Output vector (of shape `[num_elem * elem_size]` when `t_mode` = @ref CEED_NOTRANSPOSE). 1154fcbe8c06SSebastian Grimberg Ordering of the e-vector is decided by the backend. 1155ea61e9acSJeremy L Thompson @param[in] request Request or @ref CEED_REQUEST_IMMEDIATE 1156b11c1e72Sjeremylt 1157b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1158dfdf5a53Sjeremylt 11597a982d89SJeremy L. Thompson @ref User 1160b11c1e72Sjeremylt **/ 11612b730f8bSJeremy L Thompson int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) { 1162d7b241e6Sjeremylt CeedInt m, n; 1163d7b241e6Sjeremylt 1164d1d35e2fSjeremylt if (t_mode == CEED_NOTRANSPOSE) { 116505fa913cSJeremy L Thompson m = rstr->e_size; 1166d1d35e2fSjeremylt n = rstr->l_size; 1167d7b241e6Sjeremylt } else { 1168d1d35e2fSjeremylt m = rstr->l_size; 116905fa913cSJeremy L Thompson n = rstr->e_size; 1170d7b241e6Sjeremylt } 117105fa913cSJeremy L Thompson CeedCheck(n <= u->length, rstr->ceed, CEED_ERROR_DIMENSION, 11726574a04fSJeremy L Thompson "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n); 117305fa913cSJeremy L Thompson CeedCheck(m <= ru->length, rstr->ceed, CEED_ERROR_DIMENSION, 11746574a04fSJeremy L Thompson "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n); 11752b730f8bSJeremy L Thompson if (rstr->num_elem > 0) CeedCall(rstr->Apply(rstr, t_mode, u, ru, request)); 1176e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1177d7b241e6Sjeremylt } 1178d7b241e6Sjeremylt 1179d7b241e6Sjeremylt /** 11803ac8f562SJeremy L Thompson @brief Restrict an L-vector of points to a single element or apply its transpose 11813ac8f562SJeremy L Thompson 1182ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 1183ca94c3ddSJeremy L Thompson @param[in] elem Element number in range `[0, num_elem)` 11843ac8f562SJeremy L Thompson @param[in] t_mode Apply restriction or transpose 1185ca94c3ddSJeremy L Thompson @param[in] u Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE) 1186ca94c3ddSJeremy L Thompson @param[out] ru Output vector (of shape [`num_points * num_comp]` when `t_mode` = @ref CEED_NOTRANSPOSE). 11873ac8f562SJeremy L Thompson Ordering of the e-vector is decided by the backend. 11883ac8f562SJeremy L Thompson @param[in] request Request or @ref CEED_REQUEST_IMMEDIATE 11893ac8f562SJeremy L Thompson 11903ac8f562SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 11913ac8f562SJeremy L Thompson 11923ac8f562SJeremy L Thompson @ref User 11933ac8f562SJeremy L Thompson **/ 119405fa913cSJeremy L Thompson int CeedElemRestrictionApplyAtPointsInElement(CeedElemRestriction rstr, CeedInt elem, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, 11953ac8f562SJeremy L Thompson CeedRequest *request) { 11963ac8f562SJeremy L Thompson CeedInt m, n; 11973ac8f562SJeremy L Thompson 11983ac8f562SJeremy L Thompson if (t_mode == CEED_NOTRANSPOSE) { 11993ac8f562SJeremy L Thompson CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, elem, &m)); 12003ac8f562SJeremy L Thompson n = rstr->l_size; 12013ac8f562SJeremy L Thompson } else { 12023ac8f562SJeremy L Thompson m = rstr->l_size; 12033ac8f562SJeremy L Thompson CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, elem, &n)); 12043ac8f562SJeremy L Thompson } 12053ac8f562SJeremy L Thompson CeedCheck(n <= u->length, rstr->ceed, CEED_ERROR_DIMENSION, 12063ac8f562SJeremy L Thompson "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT 12073ac8f562SJeremy L Thompson ") for element %" CeedInt_FMT, 12083ac8f562SJeremy L Thompson u->length, m, n, elem); 12093ac8f562SJeremy L Thompson CeedCheck(m <= ru->length, rstr->ceed, CEED_ERROR_DIMENSION, 12103ac8f562SJeremy L Thompson "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT 12113ac8f562SJeremy L Thompson ") for element %" CeedInt_FMT, 12123ac8f562SJeremy L Thompson ru->length, m, n, elem); 12130930e4e7SJeremy L Thompson CeedCheck(elem < rstr->num_elem, rstr->ceed, CEED_ERROR_DIMENSION, 12143ac8f562SJeremy L Thompson "Cannot retrieve element %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", elem, elem, rstr->num_elem); 121505fa913cSJeremy L Thompson if (rstr->num_elem > 0) CeedCall(rstr->ApplyAtPointsInElement(rstr, elem, t_mode, u, ru, request)); 12163ac8f562SJeremy L Thompson return CEED_ERROR_SUCCESS; 12173ac8f562SJeremy L Thompson } 12183ac8f562SJeremy L Thompson 12193ac8f562SJeremy L Thompson /** 1220d9e1f99aSValeria Barra @brief Restrict an L-vector to a block of an E-vector or apply its transpose 1221be9261b7Sjeremylt 1222ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 1223ca94c3ddSJeremy 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 `[3*block_size : 4*block_size]` 1224ea61e9acSJeremy L Thompson @param[in] t_mode Apply restriction or transpose 1225ca94c3ddSJeremy L Thompson @param[in] u Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE) 1226ca94c3ddSJeremy L Thompson @param[out] ru Output vector (of shape `[block_size * elem_size]` when `t_mode` = @ref CEED_NOTRANSPOSE). 1227fcbe8c06SSebastian Grimberg Ordering of the e-vector is decided by the backend. 1228ea61e9acSJeremy L Thompson @param[in] request Request or @ref CEED_REQUEST_IMMEDIATE 1229be9261b7Sjeremylt 1230be9261b7Sjeremylt @return An error code: 0 - success, otherwise - failure 1231be9261b7Sjeremylt 12327a982d89SJeremy L. Thompson @ref Backend 1233be9261b7Sjeremylt **/ 12342b730f8bSJeremy L Thompson int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, 12352b730f8bSJeremy L Thompson CeedRequest *request) { 1236be9261b7Sjeremylt CeedInt m, n; 1237be9261b7Sjeremylt 1238ca94c3ddSJeremy L Thompson CeedCheck(rstr->ApplyBlock, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionApplyBlock"); 12396402da51SJeremy L Thompson 1240d1d35e2fSjeremylt if (t_mode == CEED_NOTRANSPOSE) { 1241e7f679fcSJeremy L Thompson m = rstr->block_size * rstr->elem_size * rstr->num_comp; 1242d1d35e2fSjeremylt n = rstr->l_size; 1243be9261b7Sjeremylt } else { 1244d1d35e2fSjeremylt m = rstr->l_size; 1245e7f679fcSJeremy L Thompson n = rstr->block_size * rstr->elem_size * rstr->num_comp; 1246be9261b7Sjeremylt } 12476574a04fSJeremy L Thompson CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION, 12486574a04fSJeremy L Thompson "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n); 12496574a04fSJeremy L Thompson CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION, 12506574a04fSJeremy L Thompson "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n); 1251e7f679fcSJeremy L Thompson CeedCheck(rstr->block_size * block <= rstr->num_elem, rstr->ceed, CEED_ERROR_DIMENSION, 1252e7f679fcSJeremy L Thompson "Cannot retrieve block %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", block, rstr->block_size * block, 12536574a04fSJeremy L Thompson rstr->num_elem); 12542b730f8bSJeremy L Thompson CeedCall(rstr->ApplyBlock(rstr, block, t_mode, u, ru, request)); 1255e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1256be9261b7Sjeremylt } 1257be9261b7Sjeremylt 1258be9261b7Sjeremylt /** 1259ca94c3ddSJeremy L Thompson @brief Get the `Ceed` associated with a `CeedElemRestriction` 1260b7c9bbdaSJeremy L Thompson 1261ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 1262ca94c3ddSJeremy L Thompson @param[out] ceed Variable to store `Ceed` 1263b7c9bbdaSJeremy L Thompson 1264b7c9bbdaSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1265b7c9bbdaSJeremy L Thompson 1266b7c9bbdaSJeremy L Thompson @ref Advanced 1267b7c9bbdaSJeremy L Thompson **/ 1268b7c9bbdaSJeremy L Thompson int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) { 1269b7c9bbdaSJeremy L Thompson *ceed = rstr->ceed; 1270b7c9bbdaSJeremy L Thompson return CEED_ERROR_SUCCESS; 1271b7c9bbdaSJeremy L Thompson } 1272b7c9bbdaSJeremy L Thompson 1273b7c9bbdaSJeremy L Thompson /** 1274d979a051Sjeremylt @brief Get the L-vector component stride 1275a681ae63Sjeremylt 1276ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 1277d1d35e2fSjeremylt @param[out] comp_stride Variable to store component stride 1278a681ae63Sjeremylt 1279a681ae63Sjeremylt @return An error code: 0 - success, otherwise - failure 1280a681ae63Sjeremylt 1281b7c9bbdaSJeremy L Thompson @ref Advanced 1282a681ae63Sjeremylt **/ 12832b730f8bSJeremy L Thompson int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, CeedInt *comp_stride) { 1284d1d35e2fSjeremylt *comp_stride = rstr->comp_stride; 1285e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1286a681ae63Sjeremylt } 1287a681ae63Sjeremylt 1288a681ae63Sjeremylt /** 1289ca94c3ddSJeremy L Thompson @brief Get the total number of elements in the range of a `CeedElemRestriction` 1290a681ae63Sjeremylt 1291ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 1292d1d35e2fSjeremylt @param[out] num_elem Variable to store number of elements 1293a681ae63Sjeremylt 1294a681ae63Sjeremylt @return An error code: 0 - success, otherwise - failure 1295a681ae63Sjeremylt 1296b7c9bbdaSJeremy L Thompson @ref Advanced 1297a681ae63Sjeremylt **/ 12982b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, CeedInt *num_elem) { 1299d1d35e2fSjeremylt *num_elem = rstr->num_elem; 1300e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1301a681ae63Sjeremylt } 1302a681ae63Sjeremylt 1303a681ae63Sjeremylt /** 1304ca94c3ddSJeremy L Thompson @brief Get the size of elements in the `CeedElemRestriction` 1305a681ae63Sjeremylt 1306ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 1307d1d35e2fSjeremylt @param[out] elem_size Variable to store size of elements 1308a681ae63Sjeremylt 1309a681ae63Sjeremylt @return An error code: 0 - success, otherwise - failure 1310a681ae63Sjeremylt 1311b7c9bbdaSJeremy L Thompson @ref Advanced 1312a681ae63Sjeremylt **/ 13132b730f8bSJeremy L Thompson int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, CeedInt *elem_size) { 1314d1d35e2fSjeremylt *elem_size = rstr->elem_size; 13152c7e7413SJeremy L Thompson return CEED_ERROR_SUCCESS; 13162c7e7413SJeremy L Thompson } 13172c7e7413SJeremy L Thompson 13182c7e7413SJeremy L Thompson /** 131907d5dec1SJeremy L Thompson 1320ca94c3ddSJeremy L Thompson @brief Get the number of points in the l-vector for a points `CeedElemRestriction` 132107d5dec1SJeremy L Thompson 1322ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 132307d5dec1SJeremy L Thompson @param[out] num_points The number of points in the l-vector 132407d5dec1SJeremy L Thompson 132507d5dec1SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 132607d5dec1SJeremy L Thompson 1327c63574e3SJeremy L Thompson @ref User 132807d5dec1SJeremy L Thompson **/ 132907d5dec1SJeremy L Thompson int CeedElemRestrictionGetNumPoints(CeedElemRestriction rstr, CeedInt *num_points) { 133007d5dec1SJeremy L Thompson Ceed ceed; 133107d5dec1SJeremy L Thompson 133207d5dec1SJeremy L Thompson CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed)); 133307d5dec1SJeremy L Thompson CeedCheck(rstr->rstr_type == CEED_RESTRICTION_POINTS, ceed, CEED_ERROR_INCOMPATIBLE, 133407d5dec1SJeremy L Thompson "Can only retrieve the number of points for a points CeedElemRestriction"); 133507d5dec1SJeremy L Thompson 133607d5dec1SJeremy L Thompson *num_points = rstr->num_points; 133707d5dec1SJeremy L Thompson return CEED_ERROR_SUCCESS; 133807d5dec1SJeremy L Thompson } 133907d5dec1SJeremy L Thompson 134007d5dec1SJeremy L Thompson /** 134107d5dec1SJeremy L Thompson 1342ca94c3ddSJeremy L Thompson @brief Get the number of points in an element of a `CeedElemRestriction` at points 134307d5dec1SJeremy L Thompson 1344ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 134507d5dec1SJeremy L Thompson @param[in] elem Index number of element to retrieve the number of points for 134607d5dec1SJeremy L Thompson @param[out] num_points The number of points in the element at index elem 134707d5dec1SJeremy L Thompson 134807d5dec1SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 134907d5dec1SJeremy L Thompson 1350c63574e3SJeremy L Thompson @ref User 135107d5dec1SJeremy L Thompson **/ 135207d5dec1SJeremy L Thompson int CeedElemRestrictionGetNumPointsInElement(CeedElemRestriction rstr, CeedInt elem, CeedInt *num_points) { 135307d5dec1SJeremy L Thompson Ceed ceed; 135407d5dec1SJeremy L Thompson const CeedInt *offsets; 135507d5dec1SJeremy L Thompson 135607d5dec1SJeremy L Thompson CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed)); 135707d5dec1SJeremy L Thompson CeedCheck(rstr->rstr_type == CEED_RESTRICTION_POINTS, ceed, CEED_ERROR_INCOMPATIBLE, 135807d5dec1SJeremy L Thompson "Can only retrieve the number of points for a points CeedElemRestriction"); 135907d5dec1SJeremy L Thompson 136007d5dec1SJeremy L Thompson CeedCall(CeedElemRestrictionGetOffsets(rstr, CEED_MEM_HOST, &offsets)); 136107d5dec1SJeremy L Thompson *num_points = offsets[elem + 1] - offsets[elem]; 136207d5dec1SJeremy L Thompson CeedCall(CeedElemRestrictionRestoreOffsets(rstr, &offsets)); 136307d5dec1SJeremy L Thompson return CEED_ERROR_SUCCESS; 136407d5dec1SJeremy L Thompson } 136507d5dec1SJeremy L Thompson 136607d5dec1SJeremy L Thompson /** 1367ca94c3ddSJeremy L Thompson @brief Get the maximum number of points in an element for a `CeedElemRestriction` at points 13682c7e7413SJeremy L Thompson 1369ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 13702c7e7413SJeremy L Thompson @param[out] max_points Variable to store size of elements 13712c7e7413SJeremy L Thompson 13722c7e7413SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 13732c7e7413SJeremy L Thompson 13742c7e7413SJeremy L Thompson @ref Advanced 13752c7e7413SJeremy L Thompson **/ 13762c7e7413SJeremy L Thompson int CeedElemRestrictionGetMaxPointsInElement(CeedElemRestriction rstr, CeedInt *max_points) { 13772c7e7413SJeremy L Thompson Ceed ceed; 13782c7e7413SJeremy L Thompson CeedInt num_elem; 13792c7e7413SJeremy L Thompson CeedRestrictionType rstr_type; 13802c7e7413SJeremy L Thompson 13812c7e7413SJeremy L Thompson CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed)); 13822c7e7413SJeremy L Thompson CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type)); 13832c7e7413SJeremy L Thompson CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, ceed, CEED_ERROR_INCOMPATIBLE, 13842c7e7413SJeremy L Thompson "Cannot compute max points for a CeedElemRestriction that does not use points"); 13852c7e7413SJeremy L Thompson 13862c7e7413SJeremy L Thompson CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem)); 13872c7e7413SJeremy L Thompson *max_points = 0; 13882c7e7413SJeremy L Thompson for (CeedInt e = 0; e < num_elem; e++) { 13892c7e7413SJeremy L Thompson CeedInt num_points; 13902c7e7413SJeremy L Thompson 13912c7e7413SJeremy L Thompson CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, e, &num_points)); 13922c7e7413SJeremy L Thompson *max_points = CeedIntMax(num_points, *max_points); 13932c7e7413SJeremy L Thompson } 1394e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1395a681ae63Sjeremylt } 1396a681ae63Sjeremylt 1397a681ae63Sjeremylt /** 1398ca94c3ddSJeremy L Thompson @brief Get the size of the l-vector for a `CeedElemRestriction` 1399a681ae63Sjeremylt 1400ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 1401d1d35e2fSjeremylt @param[out] l_size Variable to store number of nodes 1402a681ae63Sjeremylt 1403a681ae63Sjeremylt @return An error code: 0 - success, otherwise - failure 1404a681ae63Sjeremylt 1405b7c9bbdaSJeremy L Thompson @ref Advanced 1406a681ae63Sjeremylt **/ 14072b730f8bSJeremy L Thompson int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, CeedSize *l_size) { 1408d1d35e2fSjeremylt *l_size = rstr->l_size; 1409e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1410a681ae63Sjeremylt } 1411a681ae63Sjeremylt 1412a681ae63Sjeremylt /** 1413ca94c3ddSJeremy L Thompson @brief Get the number of components in the elements of a `CeedElemRestriction` 1414a681ae63Sjeremylt 1415ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 1416d1d35e2fSjeremylt @param[out] num_comp Variable to store number of components 1417a681ae63Sjeremylt 1418a681ae63Sjeremylt @return An error code: 0 - success, otherwise - failure 1419a681ae63Sjeremylt 1420b7c9bbdaSJeremy L Thompson @ref Advanced 1421a681ae63Sjeremylt **/ 14222b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, CeedInt *num_comp) { 1423d1d35e2fSjeremylt *num_comp = rstr->num_comp; 1424e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1425a681ae63Sjeremylt } 1426a681ae63Sjeremylt 1427a681ae63Sjeremylt /** 1428ca94c3ddSJeremy L Thompson @brief Get the number of blocks in a `CeedElemRestriction` 1429a681ae63Sjeremylt 1430ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 1431d1d35e2fSjeremylt @param[out] num_block Variable to store number of blocks 1432a681ae63Sjeremylt 1433a681ae63Sjeremylt @return An error code: 0 - success, otherwise - failure 1434a681ae63Sjeremylt 1435b7c9bbdaSJeremy L Thompson @ref Advanced 1436a681ae63Sjeremylt **/ 14372b730f8bSJeremy L Thompson int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, CeedInt *num_block) { 1438e7f679fcSJeremy L Thompson *num_block = rstr->num_block; 1439e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1440a681ae63Sjeremylt } 1441a681ae63Sjeremylt 1442a681ae63Sjeremylt /** 1443ca94c3ddSJeremy L Thompson @brief Get the size of blocks in the `CeedElemRestriction` 1444a681ae63Sjeremylt 1445ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 1446e7f679fcSJeremy L Thompson @param[out] block_size Variable to store size of blocks 1447a681ae63Sjeremylt 1448a681ae63Sjeremylt @return An error code: 0 - success, otherwise - failure 1449a681ae63Sjeremylt 1450b7c9bbdaSJeremy L Thompson @ref Advanced 1451a681ae63Sjeremylt **/ 1452e7f679fcSJeremy L Thompson int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, CeedInt *block_size) { 1453e7f679fcSJeremy L Thompson *block_size = rstr->block_size; 1454e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1455a681ae63Sjeremylt } 1456a681ae63Sjeremylt 1457a681ae63Sjeremylt /** 1458ca94c3ddSJeremy L Thompson @brief Get the multiplicity of nodes in a `CeedElemRestriction` 14591469ee4dSjeremylt 1460ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` 1461ca94c3ddSJeremy L Thompson @param[out] mult Vector to store multiplicity (of size `l_size`) 14621469ee4dSjeremylt 14631469ee4dSjeremylt @return An error code: 0 - success, otherwise - failure 14641469ee4dSjeremylt 14657a982d89SJeremy L. Thompson @ref User 14661469ee4dSjeremylt **/ 14672b730f8bSJeremy L Thompson int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, CeedVector mult) { 1468d1d35e2fSjeremylt CeedVector e_vec; 14691469ee4dSjeremylt 147025509ebbSRezgar Shakeri // Create e_vec to hold intermediate computation in E^T (E 1) 14712b730f8bSJeremy L Thompson CeedCall(CeedElemRestrictionCreateVector(rstr, NULL, &e_vec)); 14721469ee4dSjeremylt 147325509ebbSRezgar Shakeri // Compute e_vec = E * 1 14742b730f8bSJeremy L Thompson CeedCall(CeedVectorSetValue(mult, 1.0)); 14752b730f8bSJeremy L Thompson CeedCall(CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, CEED_REQUEST_IMMEDIATE)); 147625509ebbSRezgar Shakeri // Compute multiplicity, mult = E^T * e_vec = E^T (E 1) 14772b730f8bSJeremy L Thompson CeedCall(CeedVectorSetValue(mult, 0.0)); 14782b730f8bSJeremy L Thompson CeedCall(CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, CEED_REQUEST_IMMEDIATE)); 14791469ee4dSjeremylt // Cleanup 14802b730f8bSJeremy L Thompson CeedCall(CeedVectorDestroy(&e_vec)); 1481e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 14821469ee4dSjeremylt } 14831469ee4dSjeremylt 14841469ee4dSjeremylt /** 1485ca94c3ddSJeremy L Thompson @brief View a `CeedElemRestriction` 1486f02ca4a2SJed Brown 1487ca94c3ddSJeremy L Thompson @param[in] rstr `CeedElemRestriction` to view 1488ca94c3ddSJeremy L Thompson @param[in] stream Stream to write; typically `stdout` or a file 1489f02ca4a2SJed Brown 1490f02ca4a2SJed Brown @return Error code: 0 - success, otherwise - failure 1491f02ca4a2SJed Brown 14927a982d89SJeremy L. Thompson @ref User 1493f02ca4a2SJed Brown **/ 1494f02ca4a2SJed Brown int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) { 14950930e4e7SJeremy L Thompson CeedRestrictionType rstr_type; 14960930e4e7SJeremy L Thompson 14970930e4e7SJeremy L Thompson CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type)); 14980930e4e7SJeremy L Thompson 14990930e4e7SJeremy L Thompson if (rstr_type == CEED_RESTRICTION_POINTS) { 15000930e4e7SJeremy L Thompson CeedInt max_points; 15010930e4e7SJeremy L Thompson 15020930e4e7SJeremy L Thompson CeedCall(CeedElemRestrictionGetMaxPointsInElement(rstr, &max_points)); 15030930e4e7SJeremy L Thompson fprintf(stream, 15040930e4e7SJeremy L Thompson "CeedElemRestriction at points from (%td, %" CeedInt_FMT ") to %" CeedInt_FMT " elements with a maximum of %" CeedInt_FMT 15050930e4e7SJeremy L Thompson " points on an element\n", 15060930e4e7SJeremy L Thompson rstr->l_size, rstr->num_comp, rstr->num_elem, max_points); 15070930e4e7SJeremy L Thompson } else { 15087509a596Sjeremylt char stridesstr[500]; 15091c66c397SJeremy L Thompson 15102b730f8bSJeremy L Thompson if (rstr->strides) { 15112b730f8bSJeremy L Thompson sprintf(stridesstr, "[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "]", rstr->strides[0], rstr->strides[1], rstr->strides[2]); 15122b730f8bSJeremy L Thompson } else { 1513990fdeb6SJeremy L Thompson sprintf(stridesstr, "%" CeedInt_FMT, rstr->comp_stride); 15142b730f8bSJeremy L Thompson } 15152b730f8bSJeremy L Thompson fprintf(stream, "%sCeedElemRestriction from (%td, %" CeedInt_FMT ") to %" CeedInt_FMT " elements with %" CeedInt_FMT " nodes each and %s %s\n", 1516e7f679fcSJeremy L Thompson rstr->block_size > 1 ? "Blocked " : "", rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size, 1517d979a051Sjeremylt rstr->strides ? "strides" : "component stride", stridesstr); 15180930e4e7SJeremy L Thompson } 1519e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1520f02ca4a2SJed Brown } 1521f02ca4a2SJed Brown 1522f02ca4a2SJed Brown /** 1523ca94c3ddSJeremy L Thompson @brief Destroy a `CeedElemRestriction` 1524b11c1e72Sjeremylt 1525ca94c3ddSJeremy L Thompson @param[in,out] rstr `CeedElemRestriction` to destroy 1526b11c1e72Sjeremylt 1527b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1528dfdf5a53Sjeremylt 15297a982d89SJeremy L. Thompson @ref User 1530b11c1e72Sjeremylt **/ 15314ce2993fSjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) { 1532393ac2cdSJeremy L Thompson if (!*rstr || *rstr == CEED_ELEMRESTRICTION_NONE || --(*rstr)->ref_count > 0) { 1533ad6481ceSJeremy L Thompson *rstr = NULL; 1534ad6481ceSJeremy L Thompson return CEED_ERROR_SUCCESS; 1535ad6481ceSJeremy L Thompson } 15366574a04fSJeremy L Thompson CeedCheck((*rstr)->num_readers == 0, (*rstr)->ceed, CEED_ERROR_ACCESS, 15376574a04fSJeremy L Thompson "Cannot destroy CeedElemRestriction, a process has read access to the offset data"); 1538c17ec2beSJeremy L Thompson 1539c17ec2beSJeremy L Thompson // Only destroy backend data once between rstr and unsigned copy 15407c1dbaffSSebastian Grimberg if ((*rstr)->rstr_base) CeedCall(CeedElemRestrictionDestroy(&(*rstr)->rstr_base)); 1541c17ec2beSJeremy L Thompson else if ((*rstr)->Destroy) CeedCall((*rstr)->Destroy(*rstr)); 1542c17ec2beSJeremy L Thompson 15432b730f8bSJeremy L Thompson CeedCall(CeedFree(&(*rstr)->strides)); 15442b730f8bSJeremy L Thompson CeedCall(CeedDestroy(&(*rstr)->ceed)); 15452b730f8bSJeremy L Thompson CeedCall(CeedFree(rstr)); 1546e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1547d7b241e6Sjeremylt } 1548d7b241e6Sjeremylt 1549d7b241e6Sjeremylt /// @} 1550