1 // Copyright (c) 2017-2025, Lawrence Livermore National Security, LLC and other CEED contributors. 2 // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 3 // 4 // SPDX-License-Identifier: BSD-2-Clause 5 // 6 // This file is part of CEED: http://github.com/ceed 7 8 #include <ceed-impl.h> 9 #include <ceed.h> 10 #include <ceed/backend.h> 11 #include <stdbool.h> 12 #include <stdio.h> 13 #include <string.h> 14 15 /// @file 16 /// Implementation of CeedElemRestriction interfaces 17 18 /// ---------------------------------------------------------------------------- 19 /// CeedElemRestriction Library Internal Functions 20 /// ---------------------------------------------------------------------------- 21 /// @addtogroup CeedElemRestrictionDeveloper 22 /// @{ 23 24 /** 25 @brief Permute and pad offsets for a blocked `CeedElemRestriction` 26 27 @param[in] offsets Array of shape `[num_elem, elem_size]` 28 @param[out] block_offsets Array of permuted and padded array values of shape `[num_block, elem_size, block_size]` 29 @param[in] num_block Number of blocks 30 @param[in] num_elem Number of elements 31 @param[in] block_size Number of elements in a block 32 @param[in] elem_size Size of each element 33 34 @return An error code: 0 - success, otherwise - failure 35 36 @ref Utility 37 **/ 38 int CeedPermutePadOffsets(const CeedInt *offsets, CeedInt *block_offsets, CeedInt num_block, CeedInt num_elem, CeedInt block_size, 39 CeedInt elem_size) { 40 for (CeedInt e = 0; e < num_block * block_size; e += block_size) { 41 for (CeedInt j = 0; j < block_size; j++) { 42 for (CeedInt k = 0; k < elem_size; k++) { 43 block_offsets[e * elem_size + k * block_size + j] = offsets[CeedIntMin(e + j, num_elem - 1) * elem_size + k]; 44 } 45 } 46 } 47 return CEED_ERROR_SUCCESS; 48 } 49 50 /** 51 @brief Permute and pad orientations for a blocked `CeedElemRestriction` 52 53 @param[in] orients Array of shape `[num_elem, elem_size]` 54 @param[out] block_orients Array of permuted and padded array values of shape `[num_block, elem_size, block_size]` 55 @param[in] num_block Number of blocks 56 @param[in] num_elem Number of elements 57 @param[in] block_size Number of elements in a block 58 @param[in] elem_size Size of each element 59 60 @return An error code: 0 - success, otherwise - failure 61 62 @ref Utility 63 **/ 64 int CeedPermutePadOrients(const bool *orients, bool *block_orients, CeedInt num_block, CeedInt num_elem, CeedInt block_size, CeedInt elem_size) { 65 for (CeedInt e = 0; e < num_block * block_size; e += block_size) { 66 for (CeedInt j = 0; j < block_size; j++) { 67 for (CeedInt k = 0; k < elem_size; k++) { 68 block_orients[e * elem_size + k * block_size + j] = orients[CeedIntMin(e + j, num_elem - 1) * elem_size + k]; 69 } 70 } 71 } 72 return CEED_ERROR_SUCCESS; 73 } 74 75 /** 76 @brief Permute and pad curl-conforming orientations for a blocked `CeedElemRestriction` 77 78 @param[in] curl_orients Array of shape `[num_elem, elem_size]` 79 @param[out] block_curl_orients Array of permuted and padded array values of shape `[num_block, elem_size, block_size]` 80 @param[in] num_block Number of blocks 81 @param[in] num_elem Number of elements 82 @param[in] block_size Number of elements in a block 83 @param[in] elem_size Size of each element 84 85 @return An error code: 0 - success, otherwise - failure 86 87 @ref Utility 88 **/ 89 int CeedPermutePadCurlOrients(const CeedInt8 *curl_orients, CeedInt8 *block_curl_orients, CeedInt num_block, CeedInt num_elem, CeedInt block_size, 90 CeedInt elem_size) { 91 for (CeedInt e = 0; e < num_block * block_size; e += block_size) { 92 for (CeedInt j = 0; j < block_size; j++) { 93 for (CeedInt k = 0; k < elem_size; k++) { 94 block_curl_orients[e * elem_size + k * block_size + j] = curl_orients[CeedIntMin(e + j, num_elem - 1) * elem_size + k]; 95 } 96 } 97 } 98 return CEED_ERROR_SUCCESS; 99 } 100 101 /// @} 102 103 /// ---------------------------------------------------------------------------- 104 /// CeedElemRestriction Backend API 105 /// ---------------------------------------------------------------------------- 106 /// @addtogroup CeedElemRestrictionBackend 107 /// @{ 108 109 /** 110 @brief Get the type of a `CeedElemRestriction` 111 112 @param[in] rstr `CeedElemRestriction` 113 @param[out] rstr_type Variable to store restriction type 114 115 @return An error code: 0 - success, otherwise - failure 116 117 @ref Backend 118 **/ 119 int CeedElemRestrictionGetType(CeedElemRestriction rstr, CeedRestrictionType *rstr_type) { 120 *rstr_type = rstr->rstr_type; 121 return CEED_ERROR_SUCCESS; 122 } 123 124 /** 125 @brief Get the strided status of a `CeedElemRestriction` 126 127 @param[in] rstr `CeedElemRestriction` 128 @param[out] is_strided Variable to store strided status 129 130 @return An error code: 0 - success, otherwise - failure 131 132 @ref Backend 133 **/ 134 int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) { 135 *is_strided = (rstr->rstr_type == CEED_RESTRICTION_STRIDED); 136 return CEED_ERROR_SUCCESS; 137 } 138 139 /** 140 @brief Get the points status of a `CeedElemRestriction` 141 142 @param[in] rstr `CeedElemRestriction` 143 @param[out] is_points Variable to store points status 144 145 @return An error code: 0 - success, otherwise - failure 146 147 @ref Backend 148 **/ 149 int CeedElemRestrictionIsAtPoints(CeedElemRestriction rstr, bool *is_points) { 150 *is_points = (rstr->rstr_type == CEED_RESTRICTION_POINTS); 151 return CEED_ERROR_SUCCESS; 152 } 153 154 /** 155 @brief Check if two `CeedElemRestriction` created with @ref CeedElemRestrictionCreateAtPoints() and use the same points per element 156 157 @param[in] rstr_a First `CeedElemRestriction` 158 @param[in] rstr_b Second `CeedElemRestriction` 159 @param[out] are_compatible Variable to store compatibility status 160 161 @return An error code: 0 - success, otherwise - failure 162 163 @ref Backend 164 **/ 165 int CeedElemRestrictionAtPointsAreCompatible(CeedElemRestriction rstr_a, CeedElemRestriction rstr_b, bool *are_compatible) { 166 CeedInt num_elem_a, num_elem_b, num_points_a, num_points_b; 167 168 // Cannot compare non-points restrictions 169 CeedCheck(rstr_a->rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr_a), CEED_ERROR_UNSUPPORTED, 170 "First CeedElemRestriction must be AtPoints"); 171 CeedCheck(rstr_b->rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr_a), CEED_ERROR_UNSUPPORTED, 172 "Second CeedElemRestriction must be AtPoints"); 173 174 CeedCall(CeedElemRestrictionGetNumElements(rstr_a, &num_elem_a)); 175 CeedCall(CeedElemRestrictionGetNumElements(rstr_b, &num_elem_b)); 176 CeedCall(CeedElemRestrictionGetNumPoints(rstr_a, &num_points_a)); 177 CeedCall(CeedElemRestrictionGetNumPoints(rstr_b, &num_points_b)); 178 179 // Check size and contents of offsets arrays 180 *are_compatible = true; 181 if (num_elem_a != num_elem_b) *are_compatible = false; 182 if (num_points_a != num_points_b) *are_compatible = false; 183 if (*are_compatible) { 184 const CeedInt *offsets_a, *offsets_b; 185 186 CeedCall(CeedElemRestrictionGetOffsets(rstr_a, CEED_MEM_HOST, &offsets_a)); 187 CeedCall(CeedElemRestrictionGetOffsets(rstr_b, CEED_MEM_HOST, &offsets_b)); 188 for (CeedInt i = 0; i < num_elem_a + 1 + num_points_a; i++) *are_compatible &= offsets_a[i] == offsets_b[i]; 189 CeedCall(CeedElemRestrictionRestoreOffsets(rstr_a, &offsets_a)); 190 CeedCall(CeedElemRestrictionRestoreOffsets(rstr_b, &offsets_b)); 191 } 192 return CEED_ERROR_SUCCESS; 193 } 194 195 /** 196 @brief Get the strides of a strided `CeedElemRestriction` 197 198 @param[in] rstr `CeedElemRestriction` 199 @param[out] strides Variable to store strides array 200 201 @return An error code: 0 - success, otherwise - failure 202 203 @ref Backend 204 **/ 205 int CeedElemRestrictionGetStrides(CeedElemRestriction rstr, CeedInt strides[3]) { 206 CeedCheck(rstr->strides, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, "CeedElemRestriction has no stride data"); 207 for (CeedInt i = 0; i < 3; i++) strides[i] = rstr->strides[i]; 208 return CEED_ERROR_SUCCESS; 209 } 210 211 /** 212 @brief Get the backend stride status of a `CeedElemRestriction` 213 214 @param[in] rstr `CeedElemRestriction` 215 @param[out] has_backend_strides Variable to store stride status 216 217 @return An error code: 0 - success, otherwise - failure 218 219 @ref Backend 220 **/ 221 int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, bool *has_backend_strides) { 222 CeedCheck(rstr->strides, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, "CeedElemRestriction has no stride data"); 223 *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) && 224 (rstr->strides[2] == CEED_STRIDES_BACKEND[2])); 225 return CEED_ERROR_SUCCESS; 226 } 227 228 /** 229 @brief Get read-only access to a `CeedElemRestriction` offsets array by @ref CeedMemType 230 231 @param[in] rstr `CeedElemRestriction` to retrieve offsets 232 @param[in] mem_type Memory type on which to access the array. 233 If the backend uses a different memory type, this will perform a copy (possibly cached). 234 @param[out] offsets Array on memory type `mem_type` 235 236 @return An error code: 0 - success, otherwise - failure 237 238 @ref User 239 **/ 240 int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) { 241 if (rstr->rstr_base) { 242 CeedCall(CeedElemRestrictionGetOffsets(rstr->rstr_base, mem_type, offsets)); 243 } else { 244 CeedCheck(rstr->GetOffsets, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED, 245 "Backend does not implement CeedElemRestrictionGetOffsets"); 246 CeedCall(rstr->GetOffsets(rstr, mem_type, offsets)); 247 rstr->num_readers++; 248 } 249 return CEED_ERROR_SUCCESS; 250 } 251 252 /** 253 @brief Restore an offsets array obtained using @ref CeedElemRestrictionGetOffsets() 254 255 @param[in] rstr `CeedElemRestriction` to restore 256 @param[in] offsets Array of offset data 257 258 @return An error code: 0 - success, otherwise - failure 259 260 @ref User 261 **/ 262 int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr, const CeedInt **offsets) { 263 if (rstr->rstr_base) { 264 CeedCall(CeedElemRestrictionRestoreOffsets(rstr->rstr_base, offsets)); 265 } else { 266 *offsets = NULL; 267 rstr->num_readers--; 268 } 269 return CEED_ERROR_SUCCESS; 270 } 271 272 /** 273 @brief Get read-only access to a `CeedElemRestriction` orientations array by @ref CeedMemType 274 275 @param[in] rstr `CeedElemRestriction` to retrieve orientations 276 @param[in] mem_type Memory type on which to access the array. 277 If the backend uses a different memory type, this will perform a copy (possibly cached). 278 @param[out] orients Array on memory type `mem_type` 279 280 @return An error code: 0 - success, otherwise - failure 281 282 @ref User 283 **/ 284 int CeedElemRestrictionGetOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const bool **orients) { 285 CeedCheck(rstr->GetOrientations, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED, 286 "Backend does not implement CeedElemRestrictionGetOrientations"); 287 CeedCall(rstr->GetOrientations(rstr, mem_type, orients)); 288 rstr->num_readers++; 289 return CEED_ERROR_SUCCESS; 290 } 291 292 /** 293 @brief Restore an orientations array obtained using @ref CeedElemRestrictionGetOrientations() 294 295 @param[in] rstr `CeedElemRestriction` to restore 296 @param[in] orients Array of orientation data 297 298 @return An error code: 0 - success, otherwise - failure 299 300 @ref User 301 **/ 302 int CeedElemRestrictionRestoreOrientations(CeedElemRestriction rstr, const bool **orients) { 303 *orients = NULL; 304 rstr->num_readers--; 305 return CEED_ERROR_SUCCESS; 306 } 307 308 /** 309 @brief Get read-only access to a `CeedElemRestriction` curl-conforming orientations array by @ref CeedMemType 310 311 @param[in] rstr `CeedElemRestriction` to retrieve curl-conforming orientations 312 @param[in] mem_type Memory type on which to access the array. 313 If the backend uses a different memory type, this will perform a copy (possibly cached). 314 @param[out] curl_orients Array on memory type `mem_type` 315 316 @return An error code: 0 - success, otherwise - failure 317 318 @ref User 319 **/ 320 int CeedElemRestrictionGetCurlOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt8 **curl_orients) { 321 CeedCheck(rstr->GetCurlOrientations, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED, 322 "Backend does not implement CeedElemRestrictionGetCurlOrientations"); 323 CeedCall(rstr->GetCurlOrientations(rstr, mem_type, curl_orients)); 324 rstr->num_readers++; 325 return CEED_ERROR_SUCCESS; 326 } 327 328 /** 329 @brief Restore an orientations array obtained using @ref CeedElemRestrictionGetCurlOrientations() 330 331 @param[in] rstr `CeedElemRestriction` to restore 332 @param[in] curl_orients Array of orientation data 333 334 @return An error code: 0 - success, otherwise - failure 335 336 @ref User 337 **/ 338 int CeedElemRestrictionRestoreCurlOrientations(CeedElemRestriction rstr, const CeedInt8 **curl_orients) { 339 *curl_orients = NULL; 340 rstr->num_readers--; 341 return CEED_ERROR_SUCCESS; 342 } 343 344 /** 345 346 @brief Get the L-vector layout of a strided `CeedElemRestriction` 347 348 @param[in] rstr `CeedElemRestriction` 349 @param[out] layout Variable to store layout array, stored as `[nodes, components, elements]`. 350 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]`. 351 352 @return An error code: 0 - success, otherwise - failure 353 354 @ref Backend 355 **/ 356 int CeedElemRestrictionGetLLayout(CeedElemRestriction rstr, CeedInt layout[3]) { 357 bool has_backend_strides; 358 CeedRestrictionType rstr_type; 359 360 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type)); 361 CeedCheck(rstr_type == CEED_RESTRICTION_STRIDED, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, 362 "Only strided CeedElemRestriction have strided L-vector layout"); 363 CeedCall(CeedElemRestrictionHasBackendStrides(rstr, &has_backend_strides)); 364 if (has_backend_strides) { 365 CeedCheck(rstr->l_layout[0], CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, "CeedElemRestriction has no L-vector layout data"); 366 for (CeedInt i = 0; i < 3; i++) layout[i] = rstr->l_layout[i]; 367 } else { 368 CeedCall(CeedElemRestrictionGetStrides(rstr, layout)); 369 } 370 return CEED_ERROR_SUCCESS; 371 } 372 373 /** 374 375 @brief Set the L-vector layout of a strided `CeedElemRestriction` 376 377 @param[in] rstr `CeedElemRestriction` 378 @param[in] layout Variable to containing layout array, stored as `[nodes, components, elements]`. 379 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]`. 380 381 @return An error code: 0 - success, otherwise - failure 382 383 @ref Backend 384 **/ 385 int CeedElemRestrictionSetLLayout(CeedElemRestriction rstr, CeedInt layout[3]) { 386 CeedRestrictionType rstr_type; 387 388 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type)); 389 CeedCheck(rstr_type == CEED_RESTRICTION_STRIDED, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, 390 "Only strided CeedElemRestriction have strided L-vector layout"); 391 for (CeedInt i = 0; i < 3; i++) rstr->l_layout[i] = layout[i]; 392 return CEED_ERROR_SUCCESS; 393 } 394 395 /** 396 397 @brief Get the E-vector layout of a `CeedElemRestriction` 398 399 @param[in] rstr `CeedElemRestriction` 400 @param[out] layout Variable to store layout array, stored as `[nodes, components, elements]`. 401 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]`. 402 403 @return An error code: 0 - success, otherwise - failure 404 405 @ref Backend 406 **/ 407 int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, CeedInt layout[3]) { 408 CeedCheck(rstr->e_layout[0], CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, "CeedElemRestriction has no E-vector layout data"); 409 for (CeedInt i = 0; i < 3; i++) layout[i] = rstr->e_layout[i]; 410 return CEED_ERROR_SUCCESS; 411 } 412 413 /** 414 415 @brief Set the E-vector layout of a `CeedElemRestriction` 416 417 @param[in] rstr `CeedElemRestriction` 418 @param[in] layout Variable to containing layout array, stored as `[nodes, components, elements]`. 419 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]`. 420 421 @return An error code: 0 - success, otherwise - failure 422 423 @ref Backend 424 **/ 425 int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, CeedInt layout[3]) { 426 for (CeedInt i = 0; i < 3; i++) rstr->e_layout[i] = layout[i]; 427 return CEED_ERROR_SUCCESS; 428 } 429 430 /** 431 432 @brief Get the E-vector element offset of a `CeedElemRestriction` at points 433 434 @param[in] rstr `CeedElemRestriction` 435 @param[in] elem Element number index into E-vector for 436 @param[out] elem_offset Offset for element `elem` in the E-vector. 437 The data for point `i`, component `j`, element `elem` in the E-vector is given by `i*e_layout[0] + j*e_layout[1] + elem_offset`. 438 439 @return An error code: 0 - success, otherwise - failure 440 441 @ref Backend 442 **/ 443 int CeedElemRestrictionGetAtPointsElementOffset(CeedElemRestriction rstr, CeedInt elem, CeedSize *elem_offset) { 444 CeedInt num_comp; 445 CeedRestrictionType rstr_type; 446 447 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type)); 448 CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE, 449 "Can only compute offset for a points CeedElemRestriction"); 450 451 // Backend method 452 if (rstr->GetAtPointsElementOffset) { 453 CeedCall(rstr->GetAtPointsElementOffset(rstr, elem, elem_offset)); 454 return CEED_ERROR_SUCCESS; 455 } 456 457 // Default layout (CPU) 458 *elem_offset = 0; 459 CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp)); 460 for (CeedInt i = 0; i < elem; i++) { 461 CeedInt num_points; 462 463 CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, i, &num_points)); 464 *elem_offset += num_points * num_comp; 465 } 466 return CEED_ERROR_SUCCESS; 467 } 468 469 /** 470 471 @brief Set the E-vector size of a `CeedElemRestriction` at points 472 473 @param[in,out] rstr `CeedElemRestriction` 474 @param[in] e_size New E-vector size; must be longer than the current E-vector size 475 476 @return An error code: 0 - success, otherwise - failure 477 478 @ref Backend 479 **/ 480 int CeedElemRestrictionSetAtPointsEVectorSize(CeedElemRestriction rstr, CeedSize e_size) { 481 CeedRestrictionType rstr_type; 482 483 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type)); 484 CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE, 485 "Can only compute offset for a points CeedElemRestriction"); 486 CeedCheck(e_size >= rstr->e_size, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE, 487 "Can only increase the size of the E-vector for the CeedElemRestriction." 488 " Current size: %" CeedSize_FMT " New size: %" CeedSize_FMT, 489 rstr->e_size, e_size); 490 rstr->e_size = e_size; 491 return CEED_ERROR_SUCCESS; 492 } 493 494 /** 495 @brief Get the backend data of a `CeedElemRestriction` 496 497 @param[in] rstr `CeedElemRestriction` 498 @param[out] data Variable to store data 499 500 @return An error code: 0 - success, otherwise - failure 501 502 @ref Backend 503 **/ 504 int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) { 505 *(void **)data = rstr->data; 506 return CEED_ERROR_SUCCESS; 507 } 508 509 /** 510 @brief Set the backend data of a `CeedElemRestriction` 511 512 @param[in,out] rstr `CeedElemRestriction` 513 @param[in] data Data to set 514 515 @return An error code: 0 - success, otherwise - failure 516 517 @ref Backend 518 **/ 519 int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) { 520 rstr->data = data; 521 return CEED_ERROR_SUCCESS; 522 } 523 524 /** 525 @brief Increment the reference counter for a `CeedElemRestriction` 526 527 @param[in,out] rstr `CeedElemRestriction` to increment the reference counter 528 529 @return An error code: 0 - success, otherwise - failure 530 531 @ref Backend 532 **/ 533 int CeedElemRestrictionReference(CeedElemRestriction rstr) { 534 rstr->ref_count++; 535 return CEED_ERROR_SUCCESS; 536 } 537 538 /** 539 @brief Estimate number of FLOPs required to apply `CeedElemRestriction` in `t_mode` 540 541 @param[in] rstr `CeedElemRestriction` to estimate FLOPs for 542 @param[in] t_mode Apply restriction or transpose 543 @param[out] flops Address of variable to hold FLOPs estimate 544 545 @ref Backend 546 **/ 547 int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedSize *flops) { 548 CeedSize e_size, scale = 0; 549 CeedRestrictionType rstr_type; 550 551 CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &e_size)); 552 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type)); 553 if (t_mode == CEED_TRANSPOSE) { 554 switch (rstr_type) { 555 case CEED_RESTRICTION_POINTS: 556 scale = 0; 557 break; 558 case CEED_RESTRICTION_STRIDED: 559 case CEED_RESTRICTION_STANDARD: 560 scale = 1; 561 break; 562 case CEED_RESTRICTION_ORIENTED: 563 scale = 2; 564 break; 565 case CEED_RESTRICTION_CURL_ORIENTED: 566 scale = 6; 567 break; 568 } 569 } else { 570 switch (rstr_type) { 571 case CEED_RESTRICTION_STRIDED: 572 case CEED_RESTRICTION_STANDARD: 573 case CEED_RESTRICTION_POINTS: 574 scale = 0; 575 break; 576 case CEED_RESTRICTION_ORIENTED: 577 scale = 1; 578 break; 579 case CEED_RESTRICTION_CURL_ORIENTED: 580 scale = 5; 581 break; 582 } 583 } 584 *flops = e_size * scale; 585 return CEED_ERROR_SUCCESS; 586 } 587 588 /// @} 589 590 /// @cond DOXYGEN_SKIP 591 static struct CeedElemRestriction_private ceed_elemrestriction_none; 592 /// @endcond 593 594 /// ---------------------------------------------------------------------------- 595 /// CeedElemRestriction Public API 596 /// ---------------------------------------------------------------------------- 597 /// @addtogroup CeedElemRestrictionUser 598 /// @{ 599 600 /// Indicate that the stride is determined by the backend 601 const CeedInt CEED_STRIDES_BACKEND[3] = {0}; 602 603 /// Argument for @ref CeedOperatorSetField() indicating that the field does not require a `CeedElemRestriction` 604 const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = &ceed_elemrestriction_none; 605 606 /** 607 @brief Create a `CeedElemRestriction` 608 609 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 610 @param[in] num_elem Number of elements described in the `offsets` array 611 @param[in] elem_size Size (number of "nodes") per element 612 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 613 @param[in] comp_stride Stride between components for the same L-vector "node". 614 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`. 615 @param[in] l_size The size of the L-vector. 616 This vector may be larger than the elements and fields given by this restriction. 617 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 618 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 619 @param[in] offsets Array of shape `[num_elem, elem_size]`. 620 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. 621 All offsets must be in the range `[0, l_size - 1]`. 622 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 623 624 @return An error code: 0 - success, otherwise - failure 625 626 @ref User 627 **/ 628 int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size, 629 CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) { 630 if (!ceed->ElemRestrictionCreate) { 631 Ceed delegate; 632 633 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 634 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreate"); 635 CeedCall(CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr)); 636 CeedCall(CeedDestroy(&delegate)); 637 return CEED_ERROR_SUCCESS; 638 } 639 640 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 641 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 642 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 643 CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1"); 644 645 CeedCall(CeedCalloc(1, rstr)); 646 CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 647 (*rstr)->ref_count = 1; 648 (*rstr)->num_elem = num_elem; 649 (*rstr)->elem_size = elem_size; 650 (*rstr)->num_comp = num_comp; 651 (*rstr)->comp_stride = comp_stride; 652 (*rstr)->l_size = l_size; 653 (*rstr)->e_size = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp; 654 (*rstr)->num_block = num_elem; 655 (*rstr)->block_size = 1; 656 (*rstr)->rstr_type = CEED_RESTRICTION_STANDARD; 657 CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, NULL, *rstr)); 658 return CEED_ERROR_SUCCESS; 659 } 660 661 /** 662 @brief Create a `CeedElemRestriction` with orientation signs 663 664 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 665 @param[in] num_elem Number of elements described in the `offsets` array 666 @param[in] elem_size Size (number of "nodes") per element 667 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 668 @param[in] comp_stride Stride between components for the same L-vector "node". 669 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`. 670 @param[in] l_size The size of the L-vector. 671 This vector may be larger than the elements and fields given by this restriction. 672 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 673 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 674 @param[in] offsets Array of shape `[num_elem, elem_size]`. 675 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`. 676 All offsets must be in the range `[0, l_size - 1]`. 677 @param[in] orients Boolean array of shape `[num_elem, elem_size]` with `false` for positively oriented and `true` to flip the orientation 678 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 679 680 @return An error code: 0 - success, otherwise - failure 681 682 @ref User 683 **/ 684 int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size, 685 CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orients, 686 CeedElemRestriction *rstr) { 687 if (!ceed->ElemRestrictionCreate) { 688 Ceed delegate; 689 690 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 691 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateOriented"); 692 CeedCall(CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, orients, 693 rstr)); 694 CeedCall(CeedDestroy(&delegate)); 695 return CEED_ERROR_SUCCESS; 696 } 697 698 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 699 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 700 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 701 CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1"); 702 703 CeedCall(CeedCalloc(1, rstr)); 704 CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 705 (*rstr)->ref_count = 1; 706 (*rstr)->num_elem = num_elem; 707 (*rstr)->elem_size = elem_size; 708 (*rstr)->num_comp = num_comp; 709 (*rstr)->comp_stride = comp_stride; 710 (*rstr)->l_size = l_size; 711 (*rstr)->e_size = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp; 712 (*rstr)->num_block = num_elem; 713 (*rstr)->block_size = 1; 714 (*rstr)->rstr_type = CEED_RESTRICTION_ORIENTED; 715 CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, orients, NULL, *rstr)); 716 return CEED_ERROR_SUCCESS; 717 } 718 719 /** 720 @brief Create a `CeedElemRestriction` with a general tridiagonal transformation matrix for curl-conforming elements 721 722 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 723 @param[in] num_elem Number of elements described in the `offsets` array 724 @param[in] elem_size Size (number of "nodes") per element 725 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 726 @param[in] comp_stride Stride between components for the same L-vector "node". 727 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`. 728 @param[in] l_size The size of the L-vector. 729 This vector may be larger than the elements and fields given by this restriction. 730 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 731 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 732 @param[in] offsets Array of shape `[num_elem, elem_size]`. 733 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`. 734 All offsets must be in the range `[0, l_size - 1]`. 735 @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. 736 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). 737 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 738 739 @return An error code: 0 - success, otherwise - failure 740 741 @ref User 742 **/ 743 int CeedElemRestrictionCreateCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size, 744 CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const CeedInt8 *curl_orients, 745 CeedElemRestriction *rstr) { 746 if (!ceed->ElemRestrictionCreate) { 747 Ceed delegate; 748 749 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 750 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateCurlOriented"); 751 CeedCall(CeedElemRestrictionCreateCurlOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, 752 curl_orients, rstr)); 753 CeedCall(CeedDestroy(&delegate)); 754 return CEED_ERROR_SUCCESS; 755 } 756 757 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 758 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 759 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 760 CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1"); 761 762 CeedCall(CeedCalloc(1, rstr)); 763 CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 764 (*rstr)->ref_count = 1; 765 (*rstr)->num_elem = num_elem; 766 (*rstr)->elem_size = elem_size; 767 (*rstr)->num_comp = num_comp; 768 (*rstr)->comp_stride = comp_stride; 769 (*rstr)->l_size = l_size; 770 (*rstr)->e_size = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp; 771 (*rstr)->num_block = num_elem; 772 (*rstr)->block_size = 1; 773 (*rstr)->rstr_type = CEED_RESTRICTION_CURL_ORIENTED; 774 CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, curl_orients, *rstr)); 775 return CEED_ERROR_SUCCESS; 776 } 777 778 /** 779 @brief Create a strided `CeedElemRestriction` 780 781 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 782 @param[in] num_elem Number of elements described by the restriction 783 @param[in] elem_size Size (number of "nodes") per element 784 @param[in] num_comp Number of field components per interpolation "node" (1 for scalar fields) 785 @param[in] l_size The size of the L-vector. 786 This vector may be larger than the elements and fields given by this restriction. 787 @param[in] strides Array for strides between `[nodes, components, elements]`. 788 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]`. 789 @ref CEED_STRIDES_BACKEND may be used for `CeedVector` ordered by the same `Ceed` backend. 790 `CEED_STRIDES_BACKEND` should only be used pass data between `CeedOperator` created with the same `Ceed` backend. 791 The L-vector layout will, in general, be different between `Ceed` backends. 792 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 793 794 @return An error code: 0 - success, otherwise - failure 795 796 @ref User 797 **/ 798 int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedSize l_size, const CeedInt strides[3], 799 CeedElemRestriction *rstr) { 800 if (!ceed->ElemRestrictionCreate) { 801 Ceed delegate; 802 803 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 804 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateStrided"); 805 CeedCall(CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, l_size, strides, rstr)); 806 CeedCall(CeedDestroy(&delegate)); 807 return CEED_ERROR_SUCCESS; 808 } 809 810 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 811 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 812 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 813 CeedCheck(l_size >= (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp, ceed, CEED_ERROR_DIMENSION, 814 "L-vector size must be at least num_elem * elem_size * num_comp. Expected: > %" CeedSize_FMT " Found: %" CeedSize_FMT, 815 (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp, l_size); 816 817 CeedCall(CeedCalloc(1, rstr)); 818 CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 819 (*rstr)->ref_count = 1; 820 (*rstr)->num_elem = num_elem; 821 (*rstr)->elem_size = elem_size; 822 (*rstr)->num_comp = num_comp; 823 (*rstr)->l_size = l_size; 824 (*rstr)->e_size = (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp; 825 (*rstr)->num_block = num_elem; 826 (*rstr)->block_size = 1; 827 (*rstr)->rstr_type = CEED_RESTRICTION_STRIDED; 828 CeedCall(CeedMalloc(3, &(*rstr)->strides)); 829 for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i]; 830 CeedCall(ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr)); 831 return CEED_ERROR_SUCCESS; 832 } 833 834 /** 835 @brief Create a points `CeedElemRestriction`, for restricting for restricting from a all local points to the current element in which they are located. 836 837 The offsets array is arranged as 838 839 element_0_start_index 840 element_1_start_index 841 ... 842 element_n_start_index 843 element_n_stop_index 844 element_0_point_0 845 element_0_point_1 846 ... 847 848 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 849 @param[in] num_elem Number of elements described in the `offsets` array 850 @param[in] num_points Number of points described in the `offsets` array 851 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields). 852 Components are assumed to be contiguous by point. 853 @param[in] l_size The size of the L-vector. 854 This vector may be larger than the elements and fields given by this restriction. 855 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 856 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 857 @param[in] offsets Array of size `num_elem + 1 + num_points`. 858 The first portion of the offsets array holds the ranges of indices corresponding to each element. 859 The second portion holds the indices for each element. 860 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 861 862 @return An error code: 0 - success, otherwise - failure 863 864 @ref Backend 865 **/ 866 int CeedElemRestrictionCreateAtPoints(Ceed ceed, CeedInt num_elem, CeedInt num_points, CeedInt num_comp, CeedSize l_size, CeedMemType mem_type, 867 CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) { 868 if (!ceed->ElemRestrictionCreateAtPoints) { 869 Ceed delegate; 870 871 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 872 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateAtPoints"); 873 CeedCall(CeedElemRestrictionCreateAtPoints(delegate, num_elem, num_points, num_comp, l_size, mem_type, copy_mode, offsets, rstr)); 874 CeedCall(CeedDestroy(&delegate)); 875 return CEED_ERROR_SUCCESS; 876 } 877 878 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 879 CeedCheck(num_points >= 0, ceed, CEED_ERROR_DIMENSION, "Number of points must be non-negative"); 880 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 881 CeedCheck(l_size >= (CeedSize)num_points * num_comp, ceed, CEED_ERROR_DIMENSION, 882 "L-vector must be at least num_points * num_comp. Expected: > %" CeedSize_FMT " Found: %" CeedSize_FMT, (CeedSize)num_points * num_comp, 883 l_size); 884 885 CeedCall(CeedCalloc(1, rstr)); 886 CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 887 (*rstr)->ref_count = 1; 888 (*rstr)->num_elem = num_elem; 889 (*rstr)->num_points = num_points; 890 (*rstr)->num_comp = num_comp; 891 (*rstr)->comp_stride = 1; 892 (*rstr)->l_size = l_size; 893 (*rstr)->e_size = (CeedSize)num_points * (CeedSize)num_comp; 894 (*rstr)->num_block = num_elem; 895 (*rstr)->block_size = 1; 896 (*rstr)->rstr_type = CEED_RESTRICTION_POINTS; 897 CeedCall(ceed->ElemRestrictionCreateAtPoints(mem_type, copy_mode, offsets, NULL, NULL, *rstr)); 898 return CEED_ERROR_SUCCESS; 899 } 900 901 /** 902 @brief Create a blocked `CeedElemRestriction`, typically only used by backends 903 904 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 905 @param[in] num_elem Number of elements described in the `offsets` array 906 @param[in] elem_size Size (number of unknowns) per element 907 @param[in] block_size Number of elements in a block 908 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 909 @param[in] comp_stride Stride between components for the same L-vector "node". 910 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`. 911 @param[in] l_size The size of the L-vector. 912 This vector may be larger than the elements and fields given by this restriction. 913 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 914 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 915 @param[in] offsets Array of shape `[num_elem, elem_size]`. 916 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`. 917 All offsets must be in the range `[0, l_size - 1]`. 918 The backend will permute and pad this array to the desired ordering for the blocksize, which is typically given by the backend. 919 The default reordering is to interlace elements. 920 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 921 922 @return An error code: 0 - success, otherwise - failure 923 924 @ref Backend 925 **/ 926 int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedInt comp_stride, 927 CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, 928 CeedElemRestriction *rstr) { 929 CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size); 930 931 if (!ceed->ElemRestrictionCreateBlocked) { 932 Ceed delegate; 933 934 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 935 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlocked"); 936 CeedCall(CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, 937 rstr)); 938 CeedCall(CeedDestroy(&delegate)); 939 return CEED_ERROR_SUCCESS; 940 } 941 942 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 943 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 944 CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1"); 945 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 946 CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1"); 947 948 CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets)); 949 CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size)); 950 951 CeedCall(CeedCalloc(1, rstr)); 952 CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 953 (*rstr)->ref_count = 1; 954 (*rstr)->num_elem = num_elem; 955 (*rstr)->elem_size = elem_size; 956 (*rstr)->num_comp = num_comp; 957 (*rstr)->comp_stride = comp_stride; 958 (*rstr)->l_size = l_size; 959 (*rstr)->e_size = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp; 960 (*rstr)->num_block = num_block; 961 (*rstr)->block_size = block_size; 962 (*rstr)->rstr_type = CEED_RESTRICTION_STANDARD; 963 CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL, NULL, *rstr)); 964 if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets)); 965 return CEED_ERROR_SUCCESS; 966 } 967 968 /** 969 @brief Create a blocked oriented `CeedElemRestriction`, typically only used by backends 970 971 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 972 @param[in] num_elem Number of elements described in the `offsets` array. 973 @param[in] elem_size Size (number of unknowns) per element 974 @param[in] block_size Number of elements in a block 975 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 976 @param[in] comp_stride Stride between components for the same L-vector "node". 977 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`. 978 @param[in] l_size The size of the L-vector. 979 This vector may be larger than the elements and fields given by this restriction. 980 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 981 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 982 @param[in] offsets Array of shape `[num_elem, elem_size]`. 983 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`. 984 All offsets must be in the range `[0, l_size - 1]`. 985 The backend will permute and pad this array to the desired ordering for the blocksize, which is typically given by the backend. 986 The default reordering is to interlace elements. 987 @param[in] orients Boolean array of shape `[num_elem, elem_size]` with `false` for positively oriented and `true` to flip the orientation. 988 Will also be permuted and padded similarly to `offsets`. 989 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 990 991 @return An error code: 0 - success, otherwise - failure 992 993 @ref Backend 994 **/ 995 int CeedElemRestrictionCreateBlockedOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, 996 CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, 997 const CeedInt *offsets, const bool *orients, CeedElemRestriction *rstr) { 998 bool *block_orients; 999 CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size); 1000 1001 if (!ceed->ElemRestrictionCreateBlocked) { 1002 Ceed delegate; 1003 1004 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 1005 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedOriented"); 1006 CeedCall(CeedElemRestrictionCreateBlockedOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode, 1007 offsets, orients, rstr)); 1008 CeedCall(CeedDestroy(&delegate)); 1009 return CEED_ERROR_SUCCESS; 1010 } 1011 1012 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 1013 CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1"); 1014 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 1015 CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1"); 1016 1017 CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets)); 1018 CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_orients)); 1019 CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size)); 1020 CeedCall(CeedPermutePadOrients(orients, block_orients, num_block, num_elem, block_size, elem_size)); 1021 1022 CeedCall(CeedCalloc(1, rstr)); 1023 CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 1024 (*rstr)->ref_count = 1; 1025 (*rstr)->num_elem = num_elem; 1026 (*rstr)->elem_size = elem_size; 1027 (*rstr)->num_comp = num_comp; 1028 (*rstr)->comp_stride = comp_stride; 1029 (*rstr)->l_size = l_size; 1030 (*rstr)->e_size = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp; 1031 (*rstr)->num_block = num_block; 1032 (*rstr)->block_size = block_size; 1033 (*rstr)->rstr_type = CEED_RESTRICTION_ORIENTED; 1034 CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, (const bool *)block_orients, NULL, 1035 *rstr)); 1036 if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets)); 1037 return CEED_ERROR_SUCCESS; 1038 } 1039 1040 /** 1041 @brief Create a blocked curl-oriented `CeedElemRestriction`, typically only used by backends 1042 1043 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 1044 @param[in] num_elem Number of elements described in the `offsets` array. 1045 @param[in] elem_size Size (number of unknowns) per element 1046 @param[in] block_size Number of elements in a block 1047 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 1048 @param[in] comp_stride Stride between components for the same L-vector "node". 1049 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`. 1050 @param[in] l_size The size of the L-vector. 1051 This vector may be larger than the elements and fields given by this restriction. 1052 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 1053 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 1054 @param[in] offsets Array of shape `[num_elem, elem_size]`. 1055 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`. 1056 All offsets must be in the range `[0, l_size - 1]`. 1057 The backend will permute and pad this array to the desired ordering for the blocksize, which is typically given by the backend. 1058 The default reordering is to interlace elements. 1059 @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. 1060 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). 1061 Will also be permuted and padded similarly to offsets. 1062 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 1063 1064 @return An error code: 0 - success, otherwise - failure 1065 1066 @ref Backend 1067 **/ 1068 int CeedElemRestrictionCreateBlockedCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, 1069 CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, 1070 const CeedInt *offsets, const CeedInt8 *curl_orients, CeedElemRestriction *rstr) { 1071 CeedInt8 *block_curl_orients; 1072 CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size); 1073 1074 if (!ceed->ElemRestrictionCreateBlocked) { 1075 Ceed delegate; 1076 1077 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 1078 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedCurlOriented"); 1079 CeedCall(CeedElemRestrictionCreateBlockedCurlOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, 1080 copy_mode, offsets, curl_orients, rstr)); 1081 CeedCall(CeedDestroy(&delegate)); 1082 return CEED_ERROR_SUCCESS; 1083 } 1084 1085 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 1086 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 1087 CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1"); 1088 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 1089 CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1"); 1090 1091 CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets)); 1092 CeedCall(CeedCalloc(num_block * block_size * 3 * elem_size, &block_curl_orients)); 1093 CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size)); 1094 CeedCall(CeedPermutePadCurlOrients(curl_orients, block_curl_orients, num_block, num_elem, block_size, 3 * elem_size)); 1095 1096 CeedCall(CeedCalloc(1, rstr)); 1097 CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 1098 (*rstr)->ref_count = 1; 1099 (*rstr)->num_elem = num_elem; 1100 (*rstr)->elem_size = elem_size; 1101 (*rstr)->num_comp = num_comp; 1102 (*rstr)->comp_stride = comp_stride; 1103 (*rstr)->l_size = l_size; 1104 (*rstr)->e_size = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp; 1105 (*rstr)->num_block = num_block; 1106 (*rstr)->block_size = block_size; 1107 (*rstr)->rstr_type = CEED_RESTRICTION_CURL_ORIENTED; 1108 CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL, 1109 (const CeedInt8 *)block_curl_orients, *rstr)); 1110 if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets)); 1111 return CEED_ERROR_SUCCESS; 1112 } 1113 1114 /** 1115 @brief Create a blocked strided `CeedElemRestriction`, typically only used by backends 1116 1117 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 1118 @param[in] num_elem Number of elements described by the restriction 1119 @param[in] elem_size Size (number of "nodes") per element 1120 @param[in] block_size Number of elements in a block 1121 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 1122 @param[in] l_size The size of the L-vector. 1123 This vector may be larger than the elements and fields given by this restriction. 1124 @param[in] strides Array for strides between `[nodes, components, elements]`. 1125 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]`. 1126 @ref CEED_STRIDES_BACKEND may be used for `CeedVector` ordered by the same `Ceed` backend. 1127 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 1128 1129 @return An error code: 0 - success, otherwise - failure 1130 1131 @ref User 1132 **/ 1133 int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedSize l_size, 1134 const CeedInt strides[3], CeedElemRestriction *rstr) { 1135 CeedInt num_block = (num_elem / block_size) + !!(num_elem % block_size); 1136 1137 if (!ceed->ElemRestrictionCreateBlocked) { 1138 Ceed delegate; 1139 1140 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 1141 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedStrided"); 1142 CeedCall(CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, block_size, num_comp, l_size, strides, rstr)); 1143 CeedCall(CeedDestroy(&delegate)); 1144 return CEED_ERROR_SUCCESS; 1145 } 1146 1147 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 1148 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 1149 CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1"); 1150 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 1151 CeedCheck(l_size >= (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp, ceed, CEED_ERROR_DIMENSION, 1152 "L-vector size must be at least num_elem * elem_size * num_comp. Expected: > %" CeedSize_FMT " Found: %" CeedSize_FMT, 1153 (CeedSize)num_elem * (CeedSize)elem_size * (CeedSize)num_comp, l_size); 1154 1155 CeedCall(CeedCalloc(1, rstr)); 1156 CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 1157 (*rstr)->ref_count = 1; 1158 (*rstr)->num_elem = num_elem; 1159 (*rstr)->elem_size = elem_size; 1160 (*rstr)->num_comp = num_comp; 1161 (*rstr)->l_size = l_size; 1162 (*rstr)->e_size = (CeedSize)num_block * (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp; 1163 (*rstr)->num_block = num_block; 1164 (*rstr)->block_size = block_size; 1165 (*rstr)->rstr_type = CEED_RESTRICTION_STRIDED; 1166 CeedCall(CeedMalloc(3, &(*rstr)->strides)); 1167 for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i]; 1168 CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr)); 1169 return CEED_ERROR_SUCCESS; 1170 } 1171 1172 /** 1173 @brief Copy the pointer to a `CeedElemRestriction` and set @ref CeedElemRestrictionApply() implementation to use the unsigned version. 1174 1175 Both pointers should be destroyed with @ref CeedElemRestrictionDestroy(). 1176 1177 @param[in] rstr `CeedElemRestriction` to create unsigned reference to 1178 @param[in,out] rstr_unsigned Variable to store unsigned `CeedElemRestriction` 1179 1180 @return An error code: 0 - success, otherwise - failure 1181 1182 @ref User 1183 **/ 1184 int CeedElemRestrictionCreateUnsignedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unsigned) { 1185 CeedCall(CeedCalloc(1, rstr_unsigned)); 1186 1187 // Copy old rstr 1188 memcpy(*rstr_unsigned, rstr, sizeof(struct CeedElemRestriction_private)); 1189 (*rstr_unsigned)->ceed = NULL; 1190 CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unsigned)->ceed)); 1191 (*rstr_unsigned)->ref_count = 1; 1192 (*rstr_unsigned)->strides = NULL; 1193 if (rstr->strides) { 1194 CeedCall(CeedMalloc(3, &(*rstr_unsigned)->strides)); 1195 for (CeedInt i = 0; i < 3; i++) (*rstr_unsigned)->strides[i] = rstr->strides[i]; 1196 } 1197 CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unsigned)->rstr_base)); 1198 1199 // Override Apply 1200 (*rstr_unsigned)->Apply = rstr->ApplyUnsigned; 1201 return CEED_ERROR_SUCCESS; 1202 } 1203 1204 /** 1205 @brief Copy the pointer to a `CeedElemRestriction` and set @ref CeedElemRestrictionApply() implementation to use the unoriented version. 1206 1207 Both pointers should be destroyed with @ref CeedElemRestrictionDestroy(). 1208 1209 @param[in] rstr `CeedElemRestriction` to create unoriented reference to 1210 @param[in,out] rstr_unoriented Variable to store unoriented `CeedElemRestriction` 1211 1212 @return An error code: 0 - success, otherwise - failure 1213 1214 @ref User 1215 **/ 1216 int CeedElemRestrictionCreateUnorientedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unoriented) { 1217 CeedCall(CeedCalloc(1, rstr_unoriented)); 1218 1219 // Copy old rstr 1220 memcpy(*rstr_unoriented, rstr, sizeof(struct CeedElemRestriction_private)); 1221 (*rstr_unoriented)->ceed = NULL; 1222 CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unoriented)->ceed)); 1223 (*rstr_unoriented)->ref_count = 1; 1224 (*rstr_unoriented)->strides = NULL; 1225 if (rstr->strides) { 1226 CeedCall(CeedMalloc(3, &(*rstr_unoriented)->strides)); 1227 for (CeedInt i = 0; i < 3; i++) (*rstr_unoriented)->strides[i] = rstr->strides[i]; 1228 } 1229 CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unoriented)->rstr_base)); 1230 1231 // Override Apply 1232 (*rstr_unoriented)->Apply = rstr->ApplyUnoriented; 1233 return CEED_ERROR_SUCCESS; 1234 } 1235 1236 /** 1237 @brief Copy the pointer to a `CeedElemRestriction`. 1238 1239 Both pointers should be destroyed with @ref CeedElemRestrictionDestroy(). 1240 1241 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`. 1242 This `CeedElemRestriction` will be destroyed if `*rstr_copy` is the only reference to this `CeedElemRestriction`. 1243 1244 @param[in] rstr `CeedElemRestriction` to copy reference to 1245 @param[in,out] rstr_copy Variable to store copied reference 1246 1247 @return An error code: 0 - success, otherwise - failure 1248 1249 @ref User 1250 **/ 1251 int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_copy) { 1252 if (rstr != CEED_ELEMRESTRICTION_NONE) CeedCall(CeedElemRestrictionReference(rstr)); 1253 CeedCall(CeedElemRestrictionDestroy(rstr_copy)); 1254 *rstr_copy = rstr; 1255 return CEED_ERROR_SUCCESS; 1256 } 1257 1258 /** 1259 @brief Create `CeedVector` associated with a `CeedElemRestriction` 1260 1261 @param[in] rstr `CeedElemRestriction` 1262 @param[out] l_vec The address of the L-vector to be created, or `NULL` 1263 @param[out] e_vec The address of the E-vector to be created, or `NULL` 1264 1265 @return An error code: 0 - success, otherwise - failure 1266 1267 @ref User 1268 **/ 1269 int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, CeedVector *e_vec) { 1270 CeedSize e_size, l_size; 1271 Ceed ceed; 1272 1273 CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed)); 1274 CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &l_size)); 1275 CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &e_size)); 1276 if (l_vec) CeedCall(CeedVectorCreate(ceed, l_size, l_vec)); 1277 if (e_vec) CeedCall(CeedVectorCreate(ceed, e_size, e_vec)); 1278 CeedCall(CeedDestroy(&ceed)); 1279 return CEED_ERROR_SUCCESS; 1280 } 1281 1282 /** 1283 @brief Restrict an L-vector to an E-vector or apply its transpose 1284 1285 @param[in] rstr `CeedElemRestriction` 1286 @param[in] t_mode Apply restriction or transpose 1287 @param[in] u Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE) 1288 @param[out] ru Output vector (of shape `[num_elem * elem_size]` when `t_mode` = @ref CEED_NOTRANSPOSE). 1289 Ordering of the e-vector is decided by the backend. 1290 @param[in] request Request or @ref CEED_REQUEST_IMMEDIATE 1291 1292 @return An error code: 0 - success, otherwise - failure 1293 1294 @ref User 1295 **/ 1296 int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) { 1297 CeedSize min_u_len, min_ru_len, len; 1298 CeedInt num_elem; 1299 1300 if (t_mode == CEED_NOTRANSPOSE) { 1301 CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &min_ru_len)); 1302 CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_u_len)); 1303 } else { 1304 CeedCall(CeedElemRestrictionGetEVectorSize(rstr, &min_u_len)); 1305 CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_ru_len)); 1306 } 1307 CeedCall(CeedVectorGetLength(u, &len)); 1308 CeedCheck(min_u_len <= len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION, 1309 "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_ru_len, 1310 min_u_len); 1311 CeedCall(CeedVectorGetLength(ru, &len)); 1312 CeedCheck(min_ru_len <= len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION, 1313 "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_u_len, 1314 min_ru_len); 1315 CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem)); 1316 if (num_elem > 0) CeedCall(rstr->Apply(rstr, t_mode, u, ru, request)); 1317 return CEED_ERROR_SUCCESS; 1318 } 1319 1320 /** 1321 @brief Restrict an L-vector of points to a single element or apply its transpose 1322 1323 @param[in] rstr `CeedElemRestriction` 1324 @param[in] elem Element number in range `[0, num_elem)` 1325 @param[in] t_mode Apply restriction or transpose 1326 @param[in] u Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE) 1327 @param[out] ru Output vector (of shape [`num_points * num_comp]` when `t_mode` = @ref CEED_NOTRANSPOSE). 1328 Ordering of the e-vector is decided by the backend. 1329 @param[in] request Request or @ref CEED_REQUEST_IMMEDIATE 1330 1331 @return An error code: 0 - success, otherwise - failure 1332 1333 @ref User 1334 **/ 1335 int CeedElemRestrictionApplyAtPointsInElement(CeedElemRestriction rstr, CeedInt elem, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, 1336 CeedRequest *request) { 1337 CeedSize min_u_len, min_ru_len, len; 1338 CeedInt num_elem; 1339 1340 CeedCheck(rstr->ApplyAtPointsInElement, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED, 1341 "Backend does not implement CeedElemRestrictionApplyAtPointsInElement"); 1342 1343 if (t_mode == CEED_NOTRANSPOSE) { 1344 CeedInt num_points, num_comp; 1345 1346 CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_u_len)); 1347 CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, elem, &num_points)); 1348 CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp)); 1349 min_ru_len = (CeedSize)num_points * (CeedSize)num_comp; 1350 } else { 1351 CeedInt num_points, num_comp; 1352 1353 CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, elem, &num_points)); 1354 CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp)); 1355 min_u_len = (CeedSize)num_points * (CeedSize)num_comp; 1356 CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_ru_len)); 1357 } 1358 CeedCall(CeedVectorGetLength(u, &len)); 1359 CeedCheck(min_u_len <= len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION, 1360 "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT 1361 ") for element %" CeedInt_FMT, 1362 len, min_ru_len, min_u_len, elem); 1363 CeedCall(CeedVectorGetLength(ru, &len)); 1364 CeedCheck(min_ru_len <= len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION, 1365 "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT 1366 ") for element %" CeedInt_FMT, 1367 len, min_ru_len, min_u_len, elem); 1368 CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem)); 1369 CeedCheck(elem < num_elem, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION, 1370 "Cannot retrieve element %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", elem, elem, num_elem); 1371 if (num_elem > 0) CeedCall(rstr->ApplyAtPointsInElement(rstr, elem, t_mode, u, ru, request)); 1372 return CEED_ERROR_SUCCESS; 1373 } 1374 1375 /** 1376 @brief Restrict an L-vector to a block of an E-vector or apply its transpose 1377 1378 @param[in] rstr `CeedElemRestriction` 1379 @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]` 1380 @param[in] t_mode Apply restriction or transpose 1381 @param[in] u Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE) 1382 @param[out] ru Output vector (of shape `[block_size * elem_size]` when `t_mode` = @ref CEED_NOTRANSPOSE). 1383 Ordering of the e-vector is decided by the backend. 1384 @param[in] request Request or @ref CEED_REQUEST_IMMEDIATE 1385 1386 @return An error code: 0 - success, otherwise - failure 1387 1388 @ref Backend 1389 **/ 1390 int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, 1391 CeedRequest *request) { 1392 CeedSize min_u_len, min_ru_len, len; 1393 CeedInt block_size, num_elem; 1394 1395 CeedCheck(rstr->ApplyBlock, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_UNSUPPORTED, 1396 "Backend does not implement CeedElemRestrictionApplyBlock"); 1397 1398 CeedCall(CeedElemRestrictionGetBlockSize(rstr, &block_size)); 1399 if (t_mode == CEED_NOTRANSPOSE) { 1400 CeedInt elem_size, num_comp; 1401 1402 CeedCall(CeedElemRestrictionGetElementSize(rstr, &elem_size)); 1403 CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp)); 1404 CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_u_len)); 1405 min_ru_len = (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp; 1406 } else { 1407 CeedInt elem_size, num_comp; 1408 1409 CeedCall(CeedElemRestrictionGetElementSize(rstr, &elem_size)); 1410 CeedCall(CeedElemRestrictionGetNumComponents(rstr, &num_comp)); 1411 CeedCall(CeedElemRestrictionGetLVectorSize(rstr, &min_ru_len)); 1412 min_u_len = (CeedSize)block_size * (CeedSize)elem_size * (CeedSize)num_comp; 1413 } 1414 CeedCall(CeedVectorGetLength(u, &len)); 1415 CeedCheck(min_u_len == len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION, 1416 "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_u_len, 1417 min_ru_len); 1418 CeedCall(CeedVectorGetLength(ru, &len)); 1419 CeedCheck(min_ru_len == len, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION, 1420 "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", len, min_ru_len, 1421 min_u_len); 1422 CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem)); 1423 CeedCheck(block_size * block <= num_elem, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_DIMENSION, 1424 "Cannot retrieve block %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", block, block_size * block, 1425 num_elem); 1426 CeedCall(rstr->ApplyBlock(rstr, block, t_mode, u, ru, request)); 1427 return CEED_ERROR_SUCCESS; 1428 } 1429 1430 /** 1431 @brief Get the `Ceed` associated with a `CeedElemRestriction` 1432 1433 @param[in] rstr `CeedElemRestriction` 1434 @param[out] ceed Variable to store `Ceed` 1435 1436 @return An error code: 0 - success, otherwise - failure 1437 1438 @ref Advanced 1439 **/ 1440 int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) { 1441 *ceed = NULL; 1442 CeedCall(CeedReferenceCopy(CeedElemRestrictionReturnCeed(rstr), ceed)); 1443 return CEED_ERROR_SUCCESS; 1444 } 1445 1446 /** 1447 @brief Return the `Ceed` associated with a `CeedElemRestriction` 1448 1449 @param[in] rstr `CeedElemRestriction` 1450 1451 @return `Ceed` associated with the `rstr` 1452 1453 @ref Advanced 1454 **/ 1455 Ceed CeedElemRestrictionReturnCeed(CeedElemRestriction rstr) { return rstr->ceed; } 1456 1457 /** 1458 @brief Get the L-vector component stride 1459 1460 @param[in] rstr `CeedElemRestriction` 1461 @param[out] comp_stride Variable to store component stride 1462 1463 @return An error code: 0 - success, otherwise - failure 1464 1465 @ref Advanced 1466 **/ 1467 int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, CeedInt *comp_stride) { 1468 *comp_stride = rstr->comp_stride; 1469 return CEED_ERROR_SUCCESS; 1470 } 1471 1472 /** 1473 @brief Get the total number of elements in the range of a `CeedElemRestriction` 1474 1475 @param[in] rstr `CeedElemRestriction` 1476 @param[out] num_elem Variable to store number of elements 1477 1478 @return An error code: 0 - success, otherwise - failure 1479 1480 @ref Advanced 1481 **/ 1482 int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, CeedInt *num_elem) { 1483 *num_elem = rstr->num_elem; 1484 return CEED_ERROR_SUCCESS; 1485 } 1486 1487 /** 1488 @brief Get the size of elements in the `CeedElemRestriction` 1489 1490 @param[in] rstr `CeedElemRestriction` 1491 @param[out] elem_size Variable to store size of elements 1492 1493 @return An error code: 0 - success, otherwise - failure 1494 1495 @ref Advanced 1496 **/ 1497 int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, CeedInt *elem_size) { 1498 *elem_size = rstr->elem_size; 1499 return CEED_ERROR_SUCCESS; 1500 } 1501 1502 /** 1503 1504 @brief Get the number of points in the offsets array for a points `CeedElemRestriction` 1505 1506 @param[in] rstr `CeedElemRestriction` 1507 @param[out] num_points The number of points in the offsets array 1508 1509 @return An error code: 0 - success, otherwise - failure 1510 1511 @ref User 1512 **/ 1513 int CeedElemRestrictionGetNumPoints(CeedElemRestriction rstr, CeedInt *num_points) { 1514 CeedRestrictionType rstr_type; 1515 1516 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type)); 1517 CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE, 1518 "Can only retrieve the number of points for a points CeedElemRestriction"); 1519 1520 *num_points = rstr->num_points; 1521 return CEED_ERROR_SUCCESS; 1522 } 1523 1524 /** 1525 1526 @brief Get the number of points in an element of a `CeedElemRestriction` at points 1527 1528 @param[in] rstr `CeedElemRestriction` 1529 @param[in] elem Index number of element to retrieve the number of points for 1530 @param[out] num_points The number of points in the element at index elem 1531 1532 @return An error code: 0 - success, otherwise - failure 1533 1534 @ref User 1535 **/ 1536 int CeedElemRestrictionGetNumPointsInElement(CeedElemRestriction rstr, CeedInt elem, CeedInt *num_points) { 1537 CeedRestrictionType rstr_type; 1538 const CeedInt *offsets; 1539 1540 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type)); 1541 CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE, 1542 "Can only retrieve the number of points for a points CeedElemRestriction"); 1543 1544 CeedCall(CeedElemRestrictionGetOffsets(rstr, CEED_MEM_HOST, &offsets)); 1545 *num_points = offsets[elem + 1] - offsets[elem]; 1546 CeedCall(CeedElemRestrictionRestoreOffsets(rstr, &offsets)); 1547 return CEED_ERROR_SUCCESS; 1548 } 1549 1550 /** 1551 @brief Get the minimum and/or maximum number of points in an element for a `CeedElemRestriction` at points 1552 1553 @param[in] rstr `CeedElemRestriction` 1554 @param[out] min_points Variable to minimum number of points in an element, or `NULL` 1555 @param[out] max_points Variable to maximum number of points in an element, or `NULL` 1556 1557 @return An error code: 0 - success, otherwise - failure 1558 1559 @ref Advanced 1560 **/ 1561 int CeedElemRestrictionGetMinMaxPointsInElement(CeedElemRestriction rstr, CeedInt *min_points, CeedInt *max_points) { 1562 CeedInt num_elem, num_points; 1563 CeedRestrictionType rstr_type; 1564 1565 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type)); 1566 CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_INCOMPATIBLE, 1567 "Cannot compute min/max points for a CeedElemRestriction that does not use points"); 1568 1569 CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem)); 1570 1571 // Exit early if there are no elements 1572 if (num_elem == 0) { 1573 if (min_points) *min_points = 0; 1574 if (max_points) *max_points = 0; 1575 return CEED_ERROR_SUCCESS; 1576 } 1577 1578 // Initialize to the number of points in the first element 1579 CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, 0, &num_points)); 1580 if (min_points) *min_points = num_points; 1581 if (max_points) *max_points = num_points; 1582 for (CeedInt e = 1; e < num_elem; e++) { 1583 CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, e, &num_points)); 1584 if (min_points) *min_points = CeedIntMin(num_points, *min_points); 1585 if (max_points) *max_points = CeedIntMax(num_points, *max_points); 1586 } 1587 return CEED_ERROR_SUCCESS; 1588 } 1589 1590 /** 1591 @brief Get the maximum number of points in an element for a `CeedElemRestriction` at points 1592 1593 @param[in] rstr `CeedElemRestriction` 1594 @param[out] max_points Variable to store maximum number of points in an element 1595 1596 @return An error code: 0 - success, otherwise - failure 1597 1598 @ref User 1599 1600 @see CeedElemRestrictionGetMinMaxPointsInElement() 1601 **/ 1602 int CeedElemRestrictionGetMaxPointsInElement(CeedElemRestriction rstr, CeedInt *max_points) { 1603 return CeedElemRestrictionGetMinMaxPointsInElement(rstr, NULL, max_points); 1604 } 1605 1606 /** 1607 @brief Get the minimum number of points in an element for a `CeedElemRestriction` at points 1608 1609 @param[in] rstr `CeedElemRestriction` 1610 @param[out] min_points Variable to store minimum number of points in an element 1611 1612 @return An error code: 0 - success, otherwise - failure 1613 1614 @ref User 1615 1616 @see CeedElemRestrictionGetMinMaxPointsInElement() 1617 **/ 1618 int CeedElemRestrictionGetMinPointsInElement(CeedElemRestriction rstr, CeedInt *min_points) { 1619 return CeedElemRestrictionGetMinMaxPointsInElement(rstr, min_points, NULL); 1620 } 1621 1622 /** 1623 @brief Get the size of the l-vector for a `CeedElemRestriction` 1624 1625 @param[in] rstr `CeedElemRestriction` 1626 @param[out] l_size Variable to store l-vector size 1627 1628 @return An error code: 0 - success, otherwise - failure 1629 1630 @ref Advanced 1631 **/ 1632 int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, CeedSize *l_size) { 1633 *l_size = rstr->l_size; 1634 return CEED_ERROR_SUCCESS; 1635 } 1636 1637 /** 1638 @brief Get the size of the e-vector for a `CeedElemRestriction` 1639 1640 @param[in] rstr `CeedElemRestriction` 1641 @param[out] e_size Variable to store e-vector size 1642 1643 @return An error code: 0 - success, otherwise - failure 1644 1645 @ref Advanced 1646 **/ 1647 int CeedElemRestrictionGetEVectorSize(CeedElemRestriction rstr, CeedSize *e_size) { 1648 *e_size = rstr->e_size; 1649 return CEED_ERROR_SUCCESS; 1650 } 1651 1652 /** 1653 @brief Get the number of components in the elements of a `CeedElemRestriction` 1654 1655 @param[in] rstr `CeedElemRestriction` 1656 @param[out] num_comp Variable to store number of components 1657 1658 @return An error code: 0 - success, otherwise - failure 1659 1660 @ref Advanced 1661 **/ 1662 int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, CeedInt *num_comp) { 1663 *num_comp = rstr->num_comp; 1664 return CEED_ERROR_SUCCESS; 1665 } 1666 1667 /** 1668 @brief Get the number of blocks in a `CeedElemRestriction` 1669 1670 @param[in] rstr `CeedElemRestriction` 1671 @param[out] num_block Variable to store number of blocks 1672 1673 @return An error code: 0 - success, otherwise - failure 1674 1675 @ref Advanced 1676 **/ 1677 int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, CeedInt *num_block) { 1678 *num_block = rstr->num_block; 1679 return CEED_ERROR_SUCCESS; 1680 } 1681 1682 /** 1683 @brief Get the size of blocks in the `CeedElemRestriction` 1684 1685 @param[in] rstr `CeedElemRestriction` 1686 @param[out] block_size Variable to store size of blocks 1687 1688 @return An error code: 0 - success, otherwise - failure 1689 1690 @ref Advanced 1691 **/ 1692 int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, CeedInt *block_size) { 1693 *block_size = rstr->block_size; 1694 return CEED_ERROR_SUCCESS; 1695 } 1696 1697 /** 1698 @brief Get the multiplicity of nodes in a `CeedElemRestriction` 1699 1700 @param[in] rstr `CeedElemRestriction` 1701 @param[out] mult Vector to store multiplicity (of size `l_size`) 1702 1703 @return An error code: 0 - success, otherwise - failure 1704 1705 @ref User 1706 **/ 1707 int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, CeedVector mult) { 1708 CeedVector e_vec; 1709 1710 // Create e_vec to hold intermediate computation in E^T (E 1) 1711 CeedCall(CeedElemRestrictionCreateVector(rstr, NULL, &e_vec)); 1712 1713 // Compute e_vec = E * 1 1714 CeedCall(CeedVectorSetValue(mult, 1.0)); 1715 CeedCall(CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, CEED_REQUEST_IMMEDIATE)); 1716 // Compute multiplicity, mult = E^T * e_vec = E^T (E 1) 1717 CeedCall(CeedVectorSetValue(mult, 0.0)); 1718 CeedCall(CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, CEED_REQUEST_IMMEDIATE)); 1719 // Cleanup 1720 CeedCall(CeedVectorDestroy(&e_vec)); 1721 return CEED_ERROR_SUCCESS; 1722 } 1723 1724 /** 1725 @brief Set the number of tabs to indent for @ref CeedElemRestrictionView() output 1726 1727 @param[in] rstr `CeedElemRestriction` to set the number of view tabs 1728 @param[in] num_tabs Number of view tabs to set 1729 1730 @return Error code: 0 - success, otherwise - failure 1731 1732 @ref User 1733 **/ 1734 int CeedElemRestrictionSetNumViewTabs(CeedElemRestriction rstr, CeedInt num_tabs) { 1735 CeedCheck(num_tabs >= 0, CeedElemRestrictionReturnCeed(rstr), CEED_ERROR_MINOR, "Number of view tabs must be non-negative"); 1736 rstr->num_tabs = num_tabs; 1737 return CEED_ERROR_SUCCESS; 1738 } 1739 1740 /** 1741 @brief Get the number of tabs to indent for @ref CeedElemRestrictionView() output 1742 1743 @param[in] rstr `CeedElemRestriction` to get the number of view tabs 1744 @param[out] num_tabs Number of view tabs 1745 1746 @return Error code: 0 - success, otherwise - failure 1747 1748 @ref User 1749 **/ 1750 int CeedElemRestrictionGetNumViewTabs(CeedElemRestriction rstr, CeedInt *num_tabs) { 1751 *num_tabs = rstr->num_tabs; 1752 return CEED_ERROR_SUCCESS; 1753 } 1754 1755 /** 1756 @brief View a `CeedElemRestriction` 1757 1758 @param[in] rstr `CeedElemRestriction` to view 1759 @param[in] stream Stream to write; typically `stdout` or a file 1760 1761 @return Error code: 0 - success, otherwise - failure 1762 1763 @ref User 1764 **/ 1765 int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) { 1766 char *tabs = NULL; 1767 CeedRestrictionType rstr_type; 1768 1769 { 1770 CeedInt num_tabs = 0; 1771 1772 CeedCall(CeedElemRestrictionGetNumViewTabs(rstr, &num_tabs)); 1773 CeedCall(CeedCalloc(CEED_TAB_WIDTH * num_tabs + 1, &tabs)); 1774 for (CeedInt i = 0; i < CEED_TAB_WIDTH * num_tabs; i++) tabs[i] = ' '; 1775 } 1776 1777 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type)); 1778 if (rstr_type == CEED_RESTRICTION_POINTS) { 1779 CeedInt max_points; 1780 1781 CeedCall(CeedElemRestrictionGetMaxPointsInElement(rstr, &max_points)); 1782 fprintf(stream, 1783 "%sCeedElemRestriction at points from (%" CeedSize_FMT ", %" CeedInt_FMT ") to %" CeedInt_FMT " elements with a maximum of %" CeedInt_FMT 1784 " points on an element\n", 1785 tabs, rstr->l_size, rstr->num_comp, rstr->num_elem, max_points); 1786 } else { 1787 char strides_str[500]; 1788 1789 if (rstr->strides) { 1790 sprintf(strides_str, "[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "]", rstr->strides[0], rstr->strides[1], rstr->strides[2]); 1791 } else { 1792 sprintf(strides_str, "%" CeedInt_FMT, rstr->comp_stride); 1793 } 1794 fprintf(stream, 1795 "%s%sCeedElemRestriction from (%" CeedSize_FMT ", %" CeedInt_FMT ") to %" CeedInt_FMT " elements with %" CeedInt_FMT 1796 " nodes each and %s %s\n", 1797 tabs, rstr->block_size > 1 ? "Blocked " : "", rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size, 1798 rstr->strides ? "strides" : "component stride", strides_str); 1799 } 1800 CeedCall(CeedFree(&tabs)); 1801 return CEED_ERROR_SUCCESS; 1802 } 1803 1804 /** 1805 @brief Destroy a `CeedElemRestriction` 1806 1807 @param[in,out] rstr `CeedElemRestriction` to destroy 1808 1809 @return An error code: 0 - success, otherwise - failure 1810 1811 @ref User 1812 **/ 1813 int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) { 1814 if (!*rstr || *rstr == CEED_ELEMRESTRICTION_NONE || --(*rstr)->ref_count > 0) { 1815 *rstr = NULL; 1816 return CEED_ERROR_SUCCESS; 1817 } 1818 CeedCheck((*rstr)->num_readers == 0, (*rstr)->ceed, CEED_ERROR_ACCESS, 1819 "Cannot destroy CeedElemRestriction, a process has read access to the offset data"); 1820 1821 // Only destroy backend data once between rstr and unsigned copy 1822 if ((*rstr)->rstr_base) CeedCall(CeedElemRestrictionDestroy(&(*rstr)->rstr_base)); 1823 else if ((*rstr)->Destroy) CeedCall((*rstr)->Destroy(*rstr)); 1824 1825 CeedCall(CeedFree(&(*rstr)->strides)); 1826 CeedCall(CeedDestroy(&(*rstr)->ceed)); 1827 CeedCall(CeedFree(rstr)); 1828 return CEED_ERROR_SUCCESS; 1829 } 1830 1831 /// @} 1832