1 // Copyright (c) 2017-2022, 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 CeedElemRestrictionIsPoints(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, rstr_a->ceed, CEED_ERROR_UNSUPPORTED, "First CeedElemRestriction must be AtPoints"); 170 CeedCheck(rstr_b->rstr_type == CEED_RESTRICTION_POINTS, rstr_b->ceed, CEED_ERROR_UNSUPPORTED, "Second CeedElemRestriction must be AtPoints"); 171 172 CeedCall(CeedElemRestrictionGetNumElements(rstr_a, &num_elem_a)); 173 CeedCall(CeedElemRestrictionGetNumElements(rstr_b, &num_elem_b)); 174 CeedCall(CeedElemRestrictionGetNumPoints(rstr_a, &num_points_a)); 175 CeedCall(CeedElemRestrictionGetNumPoints(rstr_b, &num_points_b)); 176 177 // Check size and contents of offsets arrays 178 *are_compatible = true; 179 if (num_elem_a != num_elem_b) *are_compatible = false; 180 if (num_points_a != num_points_b) *are_compatible = false; 181 if (*are_compatible) { 182 const CeedInt *offsets_a, *offsets_b; 183 184 CeedCall(CeedElemRestrictionGetOffsets(rstr_a, CEED_MEM_HOST, &offsets_a)); 185 CeedCall(CeedElemRestrictionGetOffsets(rstr_b, CEED_MEM_HOST, &offsets_b)); 186 for (CeedInt i = 0; i < num_elem_a + 1 + num_points_a; i++) *are_compatible &= offsets_a[i] == offsets_b[i]; 187 CeedCall(CeedElemRestrictionRestoreOffsets(rstr_a, &offsets_a)); 188 CeedCall(CeedElemRestrictionRestoreOffsets(rstr_b, &offsets_b)); 189 } 190 return CEED_ERROR_SUCCESS; 191 } 192 193 /** 194 @brief Get the strides of a strided `CeedElemRestriction` 195 196 @param[in] rstr `CeedElemRestriction` 197 @param[out] strides Variable to store strides array 198 199 @return An error code: 0 - success, otherwise - failure 200 201 @ref Backend 202 **/ 203 int CeedElemRestrictionGetStrides(CeedElemRestriction rstr, CeedInt strides[3]) { 204 CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "CeedElemRestriction has no stride data"); 205 for (CeedInt i = 0; i < 3; i++) strides[i] = rstr->strides[i]; 206 return CEED_ERROR_SUCCESS; 207 } 208 209 /** 210 @brief Get the backend stride status of a `CeedElemRestriction` 211 212 @param[in] rstr `CeedElemRestriction` 213 @param[out] has_backend_strides Variable to store stride status 214 215 @return An error code: 0 - success, otherwise - failure 216 217 @ref Backend 218 **/ 219 int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, bool *has_backend_strides) { 220 CeedCheck(rstr->strides, rstr->ceed, CEED_ERROR_MINOR, "CeedElemRestriction has no stride data"); 221 *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) && 222 (rstr->strides[2] == CEED_STRIDES_BACKEND[2])); 223 return CEED_ERROR_SUCCESS; 224 } 225 226 /** 227 @brief Get read-only access to a `CeedElemRestriction` offsets array by @ref CeedMemType 228 229 @param[in] rstr `CeedElemRestriction` to retrieve offsets 230 @param[in] mem_type Memory type on which to access the array. 231 If the backend uses a different memory type, this will perform a copy (possibly cached). 232 @param[out] offsets Array on memory type `mem_type` 233 234 @return An error code: 0 - success, otherwise - failure 235 236 @ref User 237 **/ 238 int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt **offsets) { 239 if (rstr->rstr_base) { 240 CeedCall(CeedElemRestrictionGetOffsets(rstr->rstr_base, mem_type, offsets)); 241 } else { 242 CeedCheck(rstr->GetOffsets, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support CeedElemRestrictionGetOffsets"); 243 CeedCall(rstr->GetOffsets(rstr, mem_type, offsets)); 244 rstr->num_readers++; 245 } 246 return CEED_ERROR_SUCCESS; 247 } 248 249 /** 250 @brief Restore an offsets array obtained using @ref CeedElemRestrictionGetOffsets() 251 252 @param[in] rstr `CeedElemRestriction` to restore 253 @param[in] offsets Array of offset data 254 255 @return An error code: 0 - success, otherwise - failure 256 257 @ref User 258 **/ 259 int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr, const CeedInt **offsets) { 260 if (rstr->rstr_base) { 261 CeedCall(CeedElemRestrictionRestoreOffsets(rstr->rstr_base, offsets)); 262 } else { 263 *offsets = NULL; 264 rstr->num_readers--; 265 } 266 return CEED_ERROR_SUCCESS; 267 } 268 269 /** 270 @brief Get read-only access to a `CeedElemRestriction` orientations array by @ref CeedMemType 271 272 @param[in] rstr `CeedElemRestriction` to retrieve orientations 273 @param[in] mem_type Memory type on which to access the array. 274 If the backend uses a different memory type, this will perform a copy (possibly cached). 275 @param[out] orients Array on memory type `mem_type` 276 277 @return An error code: 0 - success, otherwise - failure 278 279 @ref User 280 **/ 281 int CeedElemRestrictionGetOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const bool **orients) { 282 CeedCheck(rstr->GetOrientations, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support CeedElemRestrictionGetOrientations"); 283 CeedCall(rstr->GetOrientations(rstr, mem_type, orients)); 284 rstr->num_readers++; 285 return CEED_ERROR_SUCCESS; 286 } 287 288 /** 289 @brief Restore an orientations array obtained using @ref CeedElemRestrictionGetOrientations() 290 291 @param[in] rstr `CeedElemRestriction` to restore 292 @param[in] orients Array of orientation data 293 294 @return An error code: 0 - success, otherwise - failure 295 296 @ref User 297 **/ 298 int CeedElemRestrictionRestoreOrientations(CeedElemRestriction rstr, const bool **orients) { 299 *orients = NULL; 300 rstr->num_readers--; 301 return CEED_ERROR_SUCCESS; 302 } 303 304 /** 305 @brief Get read-only access to a `CeedElemRestriction` curl-conforming orientations array by @ref CeedMemType 306 307 @param[in] rstr `CeedElemRestriction` to retrieve curl-conforming orientations 308 @param[in] mem_type Memory type on which to access the array. 309 If the backend uses a different memory type, this will perform a copy (possibly cached). 310 @param[out] curl_orients Array on memory type `mem_type` 311 312 @return An error code: 0 - success, otherwise - failure 313 314 @ref User 315 **/ 316 int CeedElemRestrictionGetCurlOrientations(CeedElemRestriction rstr, CeedMemType mem_type, const CeedInt8 **curl_orients) { 317 CeedCheck(rstr->GetCurlOrientations, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support CeedElemRestrictionGetCurlOrientations"); 318 CeedCall(rstr->GetCurlOrientations(rstr, mem_type, curl_orients)); 319 rstr->num_readers++; 320 return CEED_ERROR_SUCCESS; 321 } 322 323 /** 324 @brief Restore an orientations array obtained using @ref CeedElemRestrictionGetCurlOrientations() 325 326 @param[in] rstr `CeedElemRestriction` to restore 327 @param[in] curl_orients Array of orientation data 328 329 @return An error code: 0 - success, otherwise - failure 330 331 @ref User 332 **/ 333 int CeedElemRestrictionRestoreCurlOrientations(CeedElemRestriction rstr, const CeedInt8 **curl_orients) { 334 *curl_orients = NULL; 335 rstr->num_readers--; 336 return CEED_ERROR_SUCCESS; 337 } 338 339 /** 340 341 @brief Get the L-vector layout of a strided `CeedElemRestriction` 342 343 @param[in] rstr `CeedElemRestriction` 344 @param[out] layout Variable to store layout array, stored as `[nodes, components, elements]`. 345 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]`. 346 347 @return An error code: 0 - success, otherwise - failure 348 349 @ref Backend 350 **/ 351 int CeedElemRestrictionGetLLayout(CeedElemRestriction rstr, CeedInt layout[3]) { 352 bool has_backend_strides; 353 CeedRestrictionType rstr_type; 354 355 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type)); 356 CeedCheck(rstr_type == CEED_RESTRICTION_STRIDED, rstr->ceed, CEED_ERROR_MINOR, "Only strided CeedElemRestriction have strided L-vector layout"); 357 CeedCall(CeedElemRestrictionHasBackendStrides(rstr, &has_backend_strides)); 358 if (has_backend_strides) { 359 CeedCheck(rstr->l_layout[0], rstr->ceed, CEED_ERROR_MINOR, "CeedElemRestriction has no L-vector layout data"); 360 for (CeedInt i = 0; i < 3; i++) layout[i] = rstr->l_layout[i]; 361 } else { 362 CeedCall(CeedElemRestrictionGetStrides(rstr, layout)); 363 } 364 return CEED_ERROR_SUCCESS; 365 } 366 367 /** 368 369 @brief Set the L-vector layout of a strided `CeedElemRestriction` 370 371 @param[in] rstr `CeedElemRestriction` 372 @param[in] layout Variable to containing layout array, stored as `[nodes, components, elements]`. 373 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]`. 374 375 @return An error code: 0 - success, otherwise - failure 376 377 @ref Backend 378 **/ 379 int CeedElemRestrictionSetLLayout(CeedElemRestriction rstr, CeedInt layout[3]) { 380 CeedRestrictionType rstr_type; 381 382 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type)); 383 CeedCheck(rstr_type == CEED_RESTRICTION_STRIDED, rstr->ceed, CEED_ERROR_MINOR, "Only strided CeedElemRestriction have strided L-vector layout"); 384 for (CeedInt i = 0; i < 3; i++) rstr->l_layout[i] = layout[i]; 385 return CEED_ERROR_SUCCESS; 386 } 387 388 /** 389 390 @brief Get the E-vector layout of a `CeedElemRestriction` 391 392 @param[in] rstr `CeedElemRestriction` 393 @param[out] layout Variable to store layout array, stored as `[nodes, components, elements]`. 394 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]`. 395 396 @return An error code: 0 - success, otherwise - failure 397 398 @ref Backend 399 **/ 400 int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, CeedInt layout[3]) { 401 CeedCheck(rstr->e_layout[0], rstr->ceed, CEED_ERROR_MINOR, "CeedElemRestriction has no E-vector layout data"); 402 for (CeedInt i = 0; i < 3; i++) layout[i] = rstr->e_layout[i]; 403 return CEED_ERROR_SUCCESS; 404 } 405 406 /** 407 408 @brief Set the E-vector layout of a `CeedElemRestriction` 409 410 @param[in] rstr `CeedElemRestriction` 411 @param[in] layout Variable to containing layout array, stored as `[nodes, components, elements]`. 412 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]`. 413 414 @return An error code: 0 - success, otherwise - failure 415 416 @ref Backend 417 **/ 418 int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, CeedInt layout[3]) { 419 for (CeedInt i = 0; i < 3; i++) rstr->e_layout[i] = layout[i]; 420 return CEED_ERROR_SUCCESS; 421 } 422 423 /** 424 @brief Get the backend data of a `CeedElemRestriction` 425 426 @param[in] rstr `CeedElemRestriction` 427 @param[out] data Variable to store data 428 429 @return An error code: 0 - success, otherwise - failure 430 431 @ref Backend 432 **/ 433 int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) { 434 *(void **)data = rstr->data; 435 return CEED_ERROR_SUCCESS; 436 } 437 438 /** 439 @brief Set the backend data of a `CeedElemRestriction` 440 441 @param[in,out] rstr `CeedElemRestriction` 442 @param[in] data Data to set 443 444 @return An error code: 0 - success, otherwise - failure 445 446 @ref Backend 447 **/ 448 int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) { 449 rstr->data = data; 450 return CEED_ERROR_SUCCESS; 451 } 452 453 /** 454 @brief Increment the reference counter for a `CeedElemRestriction` 455 456 @param[in,out] rstr `CeedElemRestriction` to increment the reference counter 457 458 @return An error code: 0 - success, otherwise - failure 459 460 @ref Backend 461 **/ 462 int CeedElemRestrictionReference(CeedElemRestriction rstr) { 463 rstr->ref_count++; 464 return CEED_ERROR_SUCCESS; 465 } 466 467 /** 468 @brief Estimate number of FLOPs required to apply `CeedElemRestriction` in `t_mode` 469 470 @param[in] rstr `CeedElemRestriction` to estimate FLOPs for 471 @param[in] t_mode Apply restriction or transpose 472 @param[out] flops Address of variable to hold FLOPs estimate 473 474 @ref Backend 475 **/ 476 int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedSize *flops) { 477 CeedInt e_size = rstr->num_block * rstr->block_size * rstr->elem_size * rstr->num_comp, scale = 0; 478 CeedRestrictionType rstr_type; 479 480 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type)); 481 if (rstr_type == CEED_RESTRICTION_POINTS) e_size = rstr->num_points * rstr->num_comp; 482 if (t_mode == CEED_TRANSPOSE) { 483 switch (rstr_type) { 484 case CEED_RESTRICTION_POINTS: 485 scale = 0; 486 break; 487 case CEED_RESTRICTION_STRIDED: 488 case CEED_RESTRICTION_STANDARD: 489 scale = 1; 490 break; 491 case CEED_RESTRICTION_ORIENTED: 492 scale = 2; 493 break; 494 case CEED_RESTRICTION_CURL_ORIENTED: 495 scale = 6; 496 break; 497 } 498 } else { 499 switch (rstr_type) { 500 case CEED_RESTRICTION_STRIDED: 501 case CEED_RESTRICTION_STANDARD: 502 case CEED_RESTRICTION_POINTS: 503 scale = 0; 504 break; 505 case CEED_RESTRICTION_ORIENTED: 506 scale = 1; 507 break; 508 case CEED_RESTRICTION_CURL_ORIENTED: 509 scale = 5; 510 break; 511 } 512 } 513 *flops = e_size * scale; 514 return CEED_ERROR_SUCCESS; 515 } 516 517 /// @} 518 519 /// @cond DOXYGEN_SKIP 520 static struct CeedElemRestriction_private ceed_elemrestriction_none; 521 /// @endcond 522 523 /// ---------------------------------------------------------------------------- 524 /// CeedElemRestriction Public API 525 /// ---------------------------------------------------------------------------- 526 /// @addtogroup CeedElemRestrictionUser 527 /// @{ 528 529 /// Indicate that the stride is determined by the backend 530 const CeedInt CEED_STRIDES_BACKEND[3] = {0}; 531 532 /// Argument for @ref CeedOperatorSetField() indicating that the field does not require a `CeedElemRestriction` 533 const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = &ceed_elemrestriction_none; 534 535 /** 536 @brief Create a `CeedElemRestriction` 537 538 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 539 @param[in] num_elem Number of elements described in the `offsets` array 540 @param[in] elem_size Size (number of "nodes") per element 541 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 542 @param[in] comp_stride Stride between components for the same L-vector "node". 543 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`. 544 @param[in] l_size The size of the L-vector. 545 This vector may be larger than the elements and fields given by this restriction. 546 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 547 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 548 @param[in] offsets Array of shape `[num_elem, elem_size]`. 549 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. 550 All offsets must be in the range `[0, l_size - 1]`. 551 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 552 553 @return An error code: 0 - success, otherwise - failure 554 555 @ref User 556 **/ 557 int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size, 558 CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) { 559 if (!ceed->ElemRestrictionCreate) { 560 Ceed delegate; 561 562 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 563 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreate"); 564 CeedCall(CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, rstr)); 565 return CEED_ERROR_SUCCESS; 566 } 567 568 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 569 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 570 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 571 CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1"); 572 573 CeedCall(CeedCalloc(1, rstr)); 574 CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 575 (*rstr)->ref_count = 1; 576 (*rstr)->num_elem = num_elem; 577 (*rstr)->elem_size = elem_size; 578 (*rstr)->num_comp = num_comp; 579 (*rstr)->comp_stride = comp_stride; 580 (*rstr)->l_size = l_size; 581 (*rstr)->e_size = num_elem * elem_size * num_comp; 582 (*rstr)->num_block = num_elem; 583 (*rstr)->block_size = 1; 584 (*rstr)->rstr_type = CEED_RESTRICTION_STANDARD; 585 CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, NULL, *rstr)); 586 return CEED_ERROR_SUCCESS; 587 } 588 589 /** 590 @brief Create a `CeedElemRestriction` with orientation signs 591 592 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 593 @param[in] num_elem Number of elements described in the `offsets` array 594 @param[in] elem_size Size (number of "nodes") per element 595 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 596 @param[in] comp_stride Stride between components for the same L-vector "node". 597 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`. 598 @param[in] l_size The size of the L-vector. 599 This vector may be larger than the elements and fields given by this restriction. 600 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 601 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 602 @param[in] offsets Array of shape `[num_elem, elem_size]`. 603 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`. 604 All offsets must be in the range `[0, l_size - 1]`. 605 @param[in] orients Boolean array of shape `[num_elem, elem_size]` with `false` for positively oriented and `true` to flip the orientation 606 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 607 608 @return An error code: 0 - success, otherwise - failure 609 610 @ref User 611 **/ 612 int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size, 613 CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const bool *orients, 614 CeedElemRestriction *rstr) { 615 if (!ceed->ElemRestrictionCreate) { 616 Ceed delegate; 617 618 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 619 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateOriented"); 620 CeedCall( 621 CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, orients, rstr)); 622 return CEED_ERROR_SUCCESS; 623 } 624 625 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 626 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 627 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 628 CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1"); 629 630 CeedCall(CeedCalloc(1, rstr)); 631 CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 632 (*rstr)->ref_count = 1; 633 (*rstr)->num_elem = num_elem; 634 (*rstr)->elem_size = elem_size; 635 (*rstr)->num_comp = num_comp; 636 (*rstr)->comp_stride = comp_stride; 637 (*rstr)->l_size = l_size; 638 (*rstr)->e_size = num_elem * elem_size * num_comp; 639 (*rstr)->num_block = num_elem; 640 (*rstr)->block_size = 1; 641 (*rstr)->rstr_type = CEED_RESTRICTION_ORIENTED; 642 CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, orients, NULL, *rstr)); 643 return CEED_ERROR_SUCCESS; 644 } 645 646 /** 647 @brief Create a `CeedElemRestriction` with a general tridiagonal transformation matrix for curl-conforming elements 648 649 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 650 @param[in] num_elem Number of elements described in the `offsets` array 651 @param[in] elem_size Size (number of "nodes") per element 652 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 653 @param[in] comp_stride Stride between components for the same L-vector "node". 654 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`. 655 @param[in] l_size The size of the L-vector. 656 This vector may be larger than the elements and fields given by this restriction. 657 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 658 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 659 @param[in] offsets Array of shape `[num_elem, elem_size]`. 660 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`. 661 All offsets must be in the range `[0, l_size - 1]`. 662 @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. 663 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). 664 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 665 666 @return An error code: 0 - success, otherwise - failure 667 668 @ref User 669 **/ 670 int CeedElemRestrictionCreateCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedInt comp_stride, CeedSize l_size, 671 CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, const CeedInt8 *curl_orients, 672 CeedElemRestriction *rstr) { 673 if (!ceed->ElemRestrictionCreate) { 674 Ceed delegate; 675 676 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 677 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateCurlOriented"); 678 CeedCall(CeedElemRestrictionCreateCurlOriented(delegate, num_elem, elem_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, 679 curl_orients, rstr)); 680 return CEED_ERROR_SUCCESS; 681 } 682 683 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 684 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 685 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 686 CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1"); 687 688 CeedCall(CeedCalloc(1, rstr)); 689 CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 690 (*rstr)->ref_count = 1; 691 (*rstr)->num_elem = num_elem; 692 (*rstr)->elem_size = elem_size; 693 (*rstr)->num_comp = num_comp; 694 (*rstr)->comp_stride = comp_stride; 695 (*rstr)->l_size = l_size; 696 (*rstr)->e_size = num_elem * elem_size * num_comp; 697 (*rstr)->num_block = num_elem; 698 (*rstr)->block_size = 1; 699 (*rstr)->rstr_type = CEED_RESTRICTION_CURL_ORIENTED; 700 CeedCall(ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, NULL, curl_orients, *rstr)); 701 return CEED_ERROR_SUCCESS; 702 } 703 704 /** 705 @brief Create a strided `CeedElemRestriction` 706 707 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 708 @param[in] num_elem Number of elements described by the restriction 709 @param[in] elem_size Size (number of "nodes") per element 710 @param[in] num_comp Number of field components per interpolation "node" (1 for scalar fields) 711 @param[in] l_size The size of the L-vector. 712 This vector may be larger than the elements and fields given by this restriction. 713 @param[in] strides Array for strides between `[nodes, components, elements]`. 714 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]`. 715 @ref CEED_STRIDES_BACKEND may be used for `CeedVector` ordered by the same `Ceed` backend. 716 `CEED_STRIDES_BACKEND` should only be used pass data between `CeedOperator` created with the same `Ceed` backend. 717 The L-vector layout will, in general, be different between `Ceed` backends. 718 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 719 720 @return An error code: 0 - success, otherwise - failure 721 722 @ref User 723 **/ 724 int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt num_comp, CeedSize l_size, const CeedInt strides[3], 725 CeedElemRestriction *rstr) { 726 if (!ceed->ElemRestrictionCreate) { 727 Ceed delegate; 728 729 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 730 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateStrided"); 731 CeedCall(CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, l_size, strides, rstr)); 732 return CEED_ERROR_SUCCESS; 733 } 734 735 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 736 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 737 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 738 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"); 739 740 CeedCall(CeedCalloc(1, rstr)); 741 CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 742 (*rstr)->ref_count = 1; 743 (*rstr)->num_elem = num_elem; 744 (*rstr)->elem_size = elem_size; 745 (*rstr)->num_comp = num_comp; 746 (*rstr)->l_size = l_size; 747 (*rstr)->e_size = num_elem * elem_size * num_comp; 748 (*rstr)->num_block = num_elem; 749 (*rstr)->block_size = 1; 750 (*rstr)->rstr_type = CEED_RESTRICTION_STRIDED; 751 CeedCall(CeedMalloc(3, &(*rstr)->strides)); 752 for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i]; 753 CeedCall(ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr)); 754 return CEED_ERROR_SUCCESS; 755 } 756 757 /** 758 @brief Create a points `CeedElemRestriction`, for restricting for restricting from a all local points to the current element in which they are located. 759 760 The offsets array is arranged as 761 762 element_0_start_index 763 element_1_start_index 764 ... 765 element_n_start_index 766 element_n_stop_index 767 element_0_point_0 768 element_0_point_1 769 ... 770 771 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 772 @param[in] num_elem Number of elements described in the `offsets` array 773 @param[in] num_points Number of points described in the `offsets` array 774 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields). 775 Components are assumed to be contiguous by point. 776 @param[in] l_size The size of the L-vector. 777 This vector may be larger than the elements and fields given by this restriction. 778 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 779 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 780 @param[in] offsets Array of size `num_elem + 1 + num_points`. 781 The first portion of the offsets array holds the ranges of indices corresponding to each element. 782 The second portion holds the indices for each element. 783 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 784 785 @return An error code: 0 - success, otherwise - failure 786 787 @ref Backend 788 **/ 789 int CeedElemRestrictionCreateAtPoints(Ceed ceed, CeedInt num_elem, CeedInt num_points, CeedInt num_comp, CeedSize l_size, CeedMemType mem_type, 790 CeedCopyMode copy_mode, const CeedInt *offsets, CeedElemRestriction *rstr) { 791 if (!ceed->ElemRestrictionCreateAtPoints) { 792 Ceed delegate; 793 794 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 795 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateAtPoints"); 796 CeedCall(CeedElemRestrictionCreateAtPoints(delegate, num_elem, num_points, num_comp, l_size, mem_type, copy_mode, offsets, rstr)); 797 return CEED_ERROR_SUCCESS; 798 } 799 800 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 801 CeedCheck(num_points >= 0, ceed, CEED_ERROR_DIMENSION, "Number of points must be non-negative"); 802 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 803 CeedCheck(l_size >= num_points * num_comp, ceed, CEED_ERROR_DIMENSION, "L-vector must be at least num_points * num_comp"); 804 805 CeedCall(CeedCalloc(1, rstr)); 806 CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 807 (*rstr)->ref_count = 1; 808 (*rstr)->num_elem = num_elem; 809 (*rstr)->num_points = num_points; 810 (*rstr)->num_comp = num_comp; 811 (*rstr)->l_size = l_size; 812 (*rstr)->e_size = num_points * num_comp; 813 (*rstr)->num_block = num_elem; 814 (*rstr)->block_size = 1; 815 (*rstr)->rstr_type = CEED_RESTRICTION_POINTS; 816 CeedCall(ceed->ElemRestrictionCreateAtPoints(mem_type, copy_mode, offsets, NULL, NULL, *rstr)); 817 return CEED_ERROR_SUCCESS; 818 } 819 820 /** 821 @brief Create a blocked `CeedElemRestriction`, typically only used by backends 822 823 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 824 @param[in] num_elem Number of elements described in the `offsets` array 825 @param[in] elem_size Size (number of unknowns) per element 826 @param[in] block_size Number of elements in a block 827 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 828 @param[in] comp_stride Stride between components for the same L-vector "node". 829 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`. 830 @param[in] l_size The size of the L-vector. 831 This vector may be larger than the elements and fields given by this restriction. 832 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 833 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 834 @param[in] offsets Array of shape `[num_elem, elem_size]`. 835 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`. 836 All offsets must be in the range `[0, l_size - 1]`. 837 The backend will permute and pad this array to the desired ordering for the blocksize, which is typically given by the backend. 838 The default reordering is to interlace elements. 839 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 840 841 @return An error code: 0 - success, otherwise - failure 842 843 @ref Backend 844 **/ 845 int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedInt comp_stride, 846 CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, const CeedInt *offsets, 847 CeedElemRestriction *rstr) { 848 CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size); 849 850 if (!ceed->ElemRestrictionCreateBlocked) { 851 Ceed delegate; 852 853 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 854 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlocked"); 855 CeedCall(CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, 856 rstr)); 857 return CEED_ERROR_SUCCESS; 858 } 859 860 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 861 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 862 CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1"); 863 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 864 CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1"); 865 866 CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets)); 867 CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size)); 868 869 CeedCall(CeedCalloc(1, rstr)); 870 CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 871 (*rstr)->ref_count = 1; 872 (*rstr)->num_elem = num_elem; 873 (*rstr)->elem_size = elem_size; 874 (*rstr)->num_comp = num_comp; 875 (*rstr)->comp_stride = comp_stride; 876 (*rstr)->l_size = l_size; 877 (*rstr)->e_size = num_block * block_size * elem_size * num_comp; 878 (*rstr)->num_block = num_block; 879 (*rstr)->block_size = block_size; 880 (*rstr)->rstr_type = CEED_RESTRICTION_STANDARD; 881 CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL, NULL, *rstr)); 882 if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets)); 883 return CEED_ERROR_SUCCESS; 884 } 885 886 /** 887 @brief Create a blocked oriented `CeedElemRestriction`, typically only used by backends 888 889 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 890 @param[in] num_elem Number of elements described in the `offsets` array. 891 @param[in] elem_size Size (number of unknowns) per element 892 @param[in] block_size Number of elements in a block 893 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 894 @param[in] comp_stride Stride between components for the same L-vector "node". 895 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`. 896 @param[in] l_size The size of the L-vector. 897 This vector may be larger than the elements and fields given by this restriction. 898 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 899 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 900 @param[in] offsets Array of shape `[num_elem, elem_size]`. 901 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`. 902 All offsets must be in the range `[0, l_size - 1]`. 903 The backend will permute and pad this array to the desired ordering for the blocksize, which is typically given by the backend. 904 The default reordering is to interlace elements. 905 @param[in] orients Boolean array of shape `[num_elem, elem_size]` with `false` for positively oriented and `true` to flip the orientation. 906 Will also be permuted and padded similarly to `offsets`. 907 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 908 909 @return An error code: 0 - success, otherwise - failure 910 911 @ref Backend 912 **/ 913 int CeedElemRestrictionCreateBlockedOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, 914 CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, 915 const CeedInt *offsets, const bool *orients, CeedElemRestriction *rstr) { 916 bool *block_orients; 917 CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size); 918 919 if (!ceed->ElemRestrictionCreateBlocked) { 920 Ceed delegate; 921 922 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 923 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedOriented"); 924 CeedCall(CeedElemRestrictionCreateBlockedOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, copy_mode, 925 offsets, orients, rstr)); 926 return CEED_ERROR_SUCCESS; 927 } 928 929 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 930 CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1"); 931 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 932 CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1"); 933 934 CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets)); 935 CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_orients)); 936 CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size)); 937 CeedCall(CeedPermutePadOrients(orients, block_orients, num_block, num_elem, block_size, elem_size)); 938 939 CeedCall(CeedCalloc(1, rstr)); 940 CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 941 (*rstr)->ref_count = 1; 942 (*rstr)->num_elem = num_elem; 943 (*rstr)->elem_size = elem_size; 944 (*rstr)->num_comp = num_comp; 945 (*rstr)->comp_stride = comp_stride; 946 (*rstr)->l_size = l_size; 947 (*rstr)->e_size = num_block * block_size * elem_size * num_comp; 948 (*rstr)->num_block = num_block; 949 (*rstr)->block_size = block_size; 950 (*rstr)->rstr_type = CEED_RESTRICTION_ORIENTED; 951 CeedCall( 952 ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, (const bool *)block_orients, NULL, *rstr)); 953 if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets)); 954 return CEED_ERROR_SUCCESS; 955 } 956 957 /** 958 @brief Create a blocked curl-oriented `CeedElemRestriction`, typically only used by backends 959 960 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 961 @param[in] num_elem Number of elements described in the `offsets` array. 962 @param[in] elem_size Size (number of unknowns) per element 963 @param[in] block_size Number of elements in a block 964 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 965 @param[in] comp_stride Stride between components for the same L-vector "node". 966 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`. 967 @param[in] l_size The size of the L-vector. 968 This vector may be larger than the elements and fields given by this restriction. 969 @param[in] mem_type Memory type of the `offsets` array, see @ref CeedMemType 970 @param[in] copy_mode Copy mode for the `offsets` array, see @ref CeedCopyMode 971 @param[in] offsets Array of shape `[num_elem, elem_size]`. 972 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`. 973 All offsets must be in the range `[0, l_size - 1]`. 974 The backend will permute and pad this array to the desired ordering for the blocksize, which is typically given by the backend. 975 The default reordering is to interlace elements. 976 @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. 977 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). 978 Will also be permuted and padded similarly to offsets. 979 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 980 981 @return An error code: 0 - success, otherwise - failure 982 983 @ref Backend 984 **/ 985 int CeedElemRestrictionCreateBlockedCurlOriented(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, 986 CeedInt comp_stride, CeedSize l_size, CeedMemType mem_type, CeedCopyMode copy_mode, 987 const CeedInt *offsets, const CeedInt8 *curl_orients, CeedElemRestriction *rstr) { 988 CeedInt8 *block_curl_orients; 989 CeedInt *block_offsets, num_block = (num_elem / block_size) + !!(num_elem % block_size); 990 991 if (!ceed->ElemRestrictionCreateBlocked) { 992 Ceed delegate; 993 994 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 995 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedCurlOriented"); 996 CeedCall(CeedElemRestrictionCreateBlockedCurlOriented(delegate, num_elem, elem_size, block_size, num_comp, comp_stride, l_size, mem_type, 997 copy_mode, offsets, curl_orients, rstr)); 998 return CEED_ERROR_SUCCESS; 999 } 1000 1001 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 1002 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 1003 CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1"); 1004 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 1005 CeedCheck(num_comp == 1 || comp_stride > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction component stride must be at least 1"); 1006 1007 CeedCall(CeedCalloc(num_block * block_size * elem_size, &block_offsets)); 1008 CeedCall(CeedCalloc(num_block * block_size * 3 * elem_size, &block_curl_orients)); 1009 CeedCall(CeedPermutePadOffsets(offsets, block_offsets, num_block, num_elem, block_size, elem_size)); 1010 CeedCall(CeedPermutePadCurlOrients(curl_orients, block_curl_orients, num_block, num_elem, block_size, 3 * elem_size)); 1011 1012 CeedCall(CeedCalloc(1, rstr)); 1013 CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 1014 (*rstr)->ref_count = 1; 1015 (*rstr)->num_elem = num_elem; 1016 (*rstr)->elem_size = elem_size; 1017 (*rstr)->num_comp = num_comp; 1018 (*rstr)->comp_stride = comp_stride; 1019 (*rstr)->l_size = l_size; 1020 (*rstr)->e_size = num_block * block_size * elem_size * num_comp; 1021 (*rstr)->num_block = num_block; 1022 (*rstr)->block_size = block_size; 1023 (*rstr)->rstr_type = CEED_RESTRICTION_CURL_ORIENTED; 1024 CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, (const CeedInt *)block_offsets, NULL, 1025 (const CeedInt8 *)block_curl_orients, *rstr)); 1026 if (copy_mode == CEED_OWN_POINTER) CeedCall(CeedFree(&offsets)); 1027 return CEED_ERROR_SUCCESS; 1028 } 1029 1030 /** 1031 @brief Create a blocked strided `CeedElemRestriction`, typically only used by backends 1032 1033 @param[in] ceed `Ceed` context used to create the `CeedElemRestriction` 1034 @param[in] num_elem Number of elements described by the restriction 1035 @param[in] elem_size Size (number of "nodes") per element 1036 @param[in] block_size Number of elements in a block 1037 @param[in] num_comp Number of field components per interpolation node (1 for scalar fields) 1038 @param[in] l_size The size of the L-vector. 1039 This vector may be larger than the elements and fields given by this restriction. 1040 @param[in] strides Array for strides between `[nodes, components, elements]`. 1041 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]`. 1042 @ref CEED_STRIDES_BACKEND may be used for `CeedVector` ordered by the same `Ceed` backend. 1043 @param[out] rstr Address of the variable where the newly created `CeedElemRestriction` will be stored 1044 1045 @return An error code: 0 - success, otherwise - failure 1046 1047 @ref User 1048 **/ 1049 int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, CeedInt elem_size, CeedInt block_size, CeedInt num_comp, CeedSize l_size, 1050 const CeedInt strides[3], CeedElemRestriction *rstr) { 1051 CeedInt num_block = (num_elem / block_size) + !!(num_elem % block_size); 1052 1053 if (!ceed->ElemRestrictionCreateBlocked) { 1054 Ceed delegate; 1055 1056 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction")); 1057 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionCreateBlockedStrided"); 1058 CeedCall(CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, block_size, num_comp, l_size, strides, rstr)); 1059 return CEED_ERROR_SUCCESS; 1060 } 1061 1062 CeedCheck(num_elem >= 0, ceed, CEED_ERROR_DIMENSION, "Number of elements must be non-negative"); 1063 CeedCheck(elem_size > 0, ceed, CEED_ERROR_DIMENSION, "Element size must be at least 1"); 1064 CeedCheck(block_size > 0, ceed, CEED_ERROR_DIMENSION, "Block size must be at least 1"); 1065 CeedCheck(num_comp > 0, ceed, CEED_ERROR_DIMENSION, "CeedElemRestriction must have at least 1 component"); 1066 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"); 1067 1068 CeedCall(CeedCalloc(1, rstr)); 1069 CeedCall(CeedReferenceCopy(ceed, &(*rstr)->ceed)); 1070 (*rstr)->ref_count = 1; 1071 (*rstr)->num_elem = num_elem; 1072 (*rstr)->elem_size = elem_size; 1073 (*rstr)->num_comp = num_comp; 1074 (*rstr)->l_size = l_size; 1075 (*rstr)->e_size = num_block * block_size * elem_size * num_comp; 1076 (*rstr)->num_block = num_block; 1077 (*rstr)->block_size = block_size; 1078 (*rstr)->rstr_type = CEED_RESTRICTION_STRIDED; 1079 CeedCall(CeedMalloc(3, &(*rstr)->strides)); 1080 for (CeedInt i = 0; i < 3; i++) (*rstr)->strides[i] = strides[i]; 1081 CeedCall(ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, NULL, NULL, *rstr)); 1082 return CEED_ERROR_SUCCESS; 1083 } 1084 1085 /** 1086 @brief Copy the pointer to a `CeedElemRestriction` and set @ref CeedElemRestrictionApply() implementation to use the unsigned version. 1087 1088 Both pointers should be destroyed with @ref CeedElemRestrictionDestroy(). 1089 1090 @param[in] rstr `CeedElemRestriction` to create unsigned reference to 1091 @param[in,out] rstr_unsigned Variable to store unsigned `CeedElemRestriction` 1092 1093 @return An error code: 0 - success, otherwise - failure 1094 1095 @ref User 1096 **/ 1097 int CeedElemRestrictionCreateUnsignedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unsigned) { 1098 CeedCall(CeedCalloc(1, rstr_unsigned)); 1099 1100 // Copy old rstr 1101 memcpy(*rstr_unsigned, rstr, sizeof(struct CeedElemRestriction_private)); 1102 (*rstr_unsigned)->ceed = NULL; 1103 CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unsigned)->ceed)); 1104 (*rstr_unsigned)->ref_count = 1; 1105 (*rstr_unsigned)->strides = NULL; 1106 if (rstr->strides) { 1107 CeedCall(CeedMalloc(3, &(*rstr_unsigned)->strides)); 1108 for (CeedInt i = 0; i < 3; i++) (*rstr_unsigned)->strides[i] = rstr->strides[i]; 1109 } 1110 CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unsigned)->rstr_base)); 1111 1112 // Override Apply 1113 (*rstr_unsigned)->Apply = rstr->ApplyUnsigned; 1114 return CEED_ERROR_SUCCESS; 1115 } 1116 1117 /** 1118 @brief Copy the pointer to a `CeedElemRestriction` and set @ref CeedElemRestrictionApply() implementation to use the unoriented version. 1119 1120 Both pointers should be destroyed with @ref CeedElemRestrictionDestroy(). 1121 1122 @param[in] rstr `CeedElemRestriction` to create unoriented reference to 1123 @param[in,out] rstr_unoriented Variable to store unoriented `CeedElemRestriction` 1124 1125 @return An error code: 0 - success, otherwise - failure 1126 1127 @ref User 1128 **/ 1129 int CeedElemRestrictionCreateUnorientedCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_unoriented) { 1130 CeedCall(CeedCalloc(1, rstr_unoriented)); 1131 1132 // Copy old rstr 1133 memcpy(*rstr_unoriented, rstr, sizeof(struct CeedElemRestriction_private)); 1134 (*rstr_unoriented)->ceed = NULL; 1135 CeedCall(CeedReferenceCopy(rstr->ceed, &(*rstr_unoriented)->ceed)); 1136 (*rstr_unoriented)->ref_count = 1; 1137 (*rstr_unoriented)->strides = NULL; 1138 if (rstr->strides) { 1139 CeedCall(CeedMalloc(3, &(*rstr_unoriented)->strides)); 1140 for (CeedInt i = 0; i < 3; i++) (*rstr_unoriented)->strides[i] = rstr->strides[i]; 1141 } 1142 CeedCall(CeedElemRestrictionReferenceCopy(rstr, &(*rstr_unoriented)->rstr_base)); 1143 1144 // Override Apply 1145 (*rstr_unoriented)->Apply = rstr->ApplyUnoriented; 1146 return CEED_ERROR_SUCCESS; 1147 } 1148 1149 /** 1150 @brief Copy the pointer to a `CeedElemRestriction`. 1151 1152 Both pointers should be destroyed with @ref CeedElemRestrictionDestroy(). 1153 1154 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`. 1155 This `CeedElemRestriction` will be destroyed if `*rstr_copy` is the only reference to this `CeedElemRestriction`. 1156 1157 @param[in] rstr `CeedElemRestriction` to copy reference to 1158 @param[in,out] rstr_copy Variable to store copied reference 1159 1160 @return An error code: 0 - success, otherwise - failure 1161 1162 @ref User 1163 **/ 1164 int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, CeedElemRestriction *rstr_copy) { 1165 if (rstr != CEED_ELEMRESTRICTION_NONE) CeedCall(CeedElemRestrictionReference(rstr)); 1166 CeedCall(CeedElemRestrictionDestroy(rstr_copy)); 1167 *rstr_copy = rstr; 1168 return CEED_ERROR_SUCCESS; 1169 } 1170 1171 /** 1172 @brief Create `CeedVector` associated with a `CeedElemRestriction` 1173 1174 @param[in] rstr `CeedElemRestriction` 1175 @param[out] l_vec The address of the L-vector to be created, or `NULL` 1176 @param[out] e_vec The address of the E-vector to be created, or `NULL` 1177 1178 @return An error code: 0 - success, otherwise - failure 1179 1180 @ref User 1181 **/ 1182 int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, CeedVector *e_vec) { 1183 CeedSize e_size, l_size; 1184 1185 l_size = rstr->l_size; 1186 if (rstr->rstr_type == CEED_RESTRICTION_POINTS) { 1187 e_size = rstr->num_points * rstr->num_comp; 1188 } else { 1189 e_size = rstr->num_block * rstr->block_size * rstr->elem_size * rstr->num_comp; 1190 } 1191 if (l_vec) CeedCall(CeedVectorCreate(rstr->ceed, l_size, l_vec)); 1192 if (e_vec) CeedCall(CeedVectorCreate(rstr->ceed, e_size, e_vec)); 1193 return CEED_ERROR_SUCCESS; 1194 } 1195 1196 /** 1197 @brief Restrict an L-vector to an E-vector or apply its transpose 1198 1199 @param[in] rstr `CeedElemRestriction` 1200 @param[in] t_mode Apply restriction or transpose 1201 @param[in] u Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE) 1202 @param[out] ru Output vector (of shape `[num_elem * elem_size]` when `t_mode` = @ref CEED_NOTRANSPOSE). 1203 Ordering of the e-vector is decided by the backend. 1204 @param[in] request Request or @ref CEED_REQUEST_IMMEDIATE 1205 1206 @return An error code: 0 - success, otherwise - failure 1207 1208 @ref User 1209 **/ 1210 int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, CeedRequest *request) { 1211 CeedInt m, n; 1212 1213 if (t_mode == CEED_NOTRANSPOSE) { 1214 m = rstr->e_size; 1215 n = rstr->l_size; 1216 } else { 1217 m = rstr->l_size; 1218 n = rstr->e_size; 1219 } 1220 CeedCheck(n <= u->length, rstr->ceed, CEED_ERROR_DIMENSION, 1221 "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n); 1222 CeedCheck(m <= ru->length, rstr->ceed, CEED_ERROR_DIMENSION, 1223 "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n); 1224 if (rstr->num_elem > 0) CeedCall(rstr->Apply(rstr, t_mode, u, ru, request)); 1225 return CEED_ERROR_SUCCESS; 1226 } 1227 1228 /** 1229 @brief Restrict an L-vector of points to a single element or apply its transpose 1230 1231 @param[in] rstr `CeedElemRestriction` 1232 @param[in] elem Element number in range `[0, num_elem)` 1233 @param[in] t_mode Apply restriction or transpose 1234 @param[in] u Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE) 1235 @param[out] ru Output vector (of shape [`num_points * num_comp]` when `t_mode` = @ref CEED_NOTRANSPOSE). 1236 Ordering of the e-vector is decided by the backend. 1237 @param[in] request Request or @ref CEED_REQUEST_IMMEDIATE 1238 1239 @return An error code: 0 - success, otherwise - failure 1240 1241 @ref User 1242 **/ 1243 int CeedElemRestrictionApplyAtPointsInElement(CeedElemRestriction rstr, CeedInt elem, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, 1244 CeedRequest *request) { 1245 CeedInt m, n; 1246 1247 if (t_mode == CEED_NOTRANSPOSE) { 1248 CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, elem, &m)); 1249 n = rstr->l_size; 1250 } else { 1251 m = rstr->l_size; 1252 CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, elem, &n)); 1253 } 1254 CeedCheck(n <= u->length, rstr->ceed, CEED_ERROR_DIMENSION, 1255 "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT 1256 ") for element %" CeedInt_FMT, 1257 u->length, m, n, elem); 1258 CeedCheck(m <= ru->length, rstr->ceed, CEED_ERROR_DIMENSION, 1259 "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT 1260 ") for element %" CeedInt_FMT, 1261 ru->length, m, n, elem); 1262 CeedCheck(elem < rstr->num_elem, rstr->ceed, CEED_ERROR_DIMENSION, 1263 "Cannot retrieve element %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", elem, elem, rstr->num_elem); 1264 if (rstr->num_elem > 0) CeedCall(rstr->ApplyAtPointsInElement(rstr, elem, t_mode, u, ru, request)); 1265 return CEED_ERROR_SUCCESS; 1266 } 1267 1268 /** 1269 @brief Restrict an L-vector to a block of an E-vector or apply its transpose 1270 1271 @param[in] rstr `CeedElemRestriction` 1272 @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]` 1273 @param[in] t_mode Apply restriction or transpose 1274 @param[in] u Input vector (of size `l_size` when `t_mode` = @ref CEED_NOTRANSPOSE) 1275 @param[out] ru Output vector (of shape `[block_size * elem_size]` when `t_mode` = @ref CEED_NOTRANSPOSE). 1276 Ordering of the e-vector is decided by the backend. 1277 @param[in] request Request or @ref CEED_REQUEST_IMMEDIATE 1278 1279 @return An error code: 0 - success, otherwise - failure 1280 1281 @ref Backend 1282 **/ 1283 int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, CeedTransposeMode t_mode, CeedVector u, CeedVector ru, 1284 CeedRequest *request) { 1285 CeedInt m, n; 1286 1287 CeedCheck(rstr->ApplyBlock, rstr->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not implement CeedElemRestrictionApplyBlock"); 1288 1289 if (t_mode == CEED_NOTRANSPOSE) { 1290 m = rstr->block_size * rstr->elem_size * rstr->num_comp; 1291 n = rstr->l_size; 1292 } else { 1293 m = rstr->l_size; 1294 n = rstr->block_size * rstr->elem_size * rstr->num_comp; 1295 } 1296 CeedCheck(n == u->length, rstr->ceed, CEED_ERROR_DIMENSION, 1297 "Input vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", u->length, m, n); 1298 CeedCheck(m == ru->length, rstr->ceed, CEED_ERROR_DIMENSION, 1299 "Output vector size %" CeedInt_FMT " not compatible with element restriction (%" CeedInt_FMT ", %" CeedInt_FMT ")", ru->length, m, n); 1300 CeedCheck(rstr->block_size * block <= rstr->num_elem, rstr->ceed, CEED_ERROR_DIMENSION, 1301 "Cannot retrieve block %" CeedInt_FMT ", element %" CeedInt_FMT " > total elements %" CeedInt_FMT "", block, rstr->block_size * block, 1302 rstr->num_elem); 1303 CeedCall(rstr->ApplyBlock(rstr, block, t_mode, u, ru, request)); 1304 return CEED_ERROR_SUCCESS; 1305 } 1306 1307 /** 1308 @brief Get the `Ceed` associated with a `CeedElemRestriction` 1309 1310 @param[in] rstr `CeedElemRestriction` 1311 @param[out] ceed Variable to store `Ceed` 1312 1313 @return An error code: 0 - success, otherwise - failure 1314 1315 @ref Advanced 1316 **/ 1317 int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) { 1318 *ceed = rstr->ceed; 1319 return CEED_ERROR_SUCCESS; 1320 } 1321 1322 /** 1323 @brief Get the L-vector component stride 1324 1325 @param[in] rstr `CeedElemRestriction` 1326 @param[out] comp_stride Variable to store component stride 1327 1328 @return An error code: 0 - success, otherwise - failure 1329 1330 @ref Advanced 1331 **/ 1332 int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, CeedInt *comp_stride) { 1333 *comp_stride = rstr->comp_stride; 1334 return CEED_ERROR_SUCCESS; 1335 } 1336 1337 /** 1338 @brief Get the total number of elements in the range of a `CeedElemRestriction` 1339 1340 @param[in] rstr `CeedElemRestriction` 1341 @param[out] num_elem Variable to store number of elements 1342 1343 @return An error code: 0 - success, otherwise - failure 1344 1345 @ref Advanced 1346 **/ 1347 int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, CeedInt *num_elem) { 1348 *num_elem = rstr->num_elem; 1349 return CEED_ERROR_SUCCESS; 1350 } 1351 1352 /** 1353 @brief Get the size of elements in the `CeedElemRestriction` 1354 1355 @param[in] rstr `CeedElemRestriction` 1356 @param[out] elem_size Variable to store size of elements 1357 1358 @return An error code: 0 - success, otherwise - failure 1359 1360 @ref Advanced 1361 **/ 1362 int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, CeedInt *elem_size) { 1363 *elem_size = rstr->elem_size; 1364 return CEED_ERROR_SUCCESS; 1365 } 1366 1367 /** 1368 1369 @brief Get the number of points in the l-vector for a points `CeedElemRestriction` 1370 1371 @param[in] rstr `CeedElemRestriction` 1372 @param[out] num_points The number of points in the l-vector 1373 1374 @return An error code: 0 - success, otherwise - failure 1375 1376 @ref User 1377 **/ 1378 int CeedElemRestrictionGetNumPoints(CeedElemRestriction rstr, CeedInt *num_points) { 1379 Ceed ceed; 1380 1381 CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed)); 1382 CeedCheck(rstr->rstr_type == CEED_RESTRICTION_POINTS, ceed, CEED_ERROR_INCOMPATIBLE, 1383 "Can only retrieve the number of points for a points CeedElemRestriction"); 1384 1385 *num_points = rstr->num_points; 1386 return CEED_ERROR_SUCCESS; 1387 } 1388 1389 /** 1390 1391 @brief Get the number of points in an element of a `CeedElemRestriction` at points 1392 1393 @param[in] rstr `CeedElemRestriction` 1394 @param[in] elem Index number of element to retrieve the number of points for 1395 @param[out] num_points The number of points in the element at index elem 1396 1397 @return An error code: 0 - success, otherwise - failure 1398 1399 @ref User 1400 **/ 1401 int CeedElemRestrictionGetNumPointsInElement(CeedElemRestriction rstr, CeedInt elem, CeedInt *num_points) { 1402 Ceed ceed; 1403 const CeedInt *offsets; 1404 1405 CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed)); 1406 CeedCheck(rstr->rstr_type == CEED_RESTRICTION_POINTS, ceed, CEED_ERROR_INCOMPATIBLE, 1407 "Can only retrieve the number of points for a points CeedElemRestriction"); 1408 1409 CeedCall(CeedElemRestrictionGetOffsets(rstr, CEED_MEM_HOST, &offsets)); 1410 *num_points = offsets[elem + 1] - offsets[elem]; 1411 CeedCall(CeedElemRestrictionRestoreOffsets(rstr, &offsets)); 1412 return CEED_ERROR_SUCCESS; 1413 } 1414 1415 /** 1416 @brief Get the maximum number of points in an element for a `CeedElemRestriction` at points 1417 1418 @param[in] rstr `CeedElemRestriction` 1419 @param[out] max_points Variable to store size of elements 1420 1421 @return An error code: 0 - success, otherwise - failure 1422 1423 @ref Advanced 1424 **/ 1425 int CeedElemRestrictionGetMaxPointsInElement(CeedElemRestriction rstr, CeedInt *max_points) { 1426 Ceed ceed; 1427 CeedInt num_elem; 1428 CeedRestrictionType rstr_type; 1429 1430 CeedCall(CeedElemRestrictionGetCeed(rstr, &ceed)); 1431 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type)); 1432 CeedCheck(rstr_type == CEED_RESTRICTION_POINTS, ceed, CEED_ERROR_INCOMPATIBLE, 1433 "Cannot compute max points for a CeedElemRestriction that does not use points"); 1434 1435 CeedCall(CeedElemRestrictionGetNumElements(rstr, &num_elem)); 1436 *max_points = 0; 1437 for (CeedInt e = 0; e < num_elem; e++) { 1438 CeedInt num_points; 1439 1440 CeedCall(CeedElemRestrictionGetNumPointsInElement(rstr, e, &num_points)); 1441 *max_points = CeedIntMax(num_points, *max_points); 1442 } 1443 return CEED_ERROR_SUCCESS; 1444 } 1445 1446 /** 1447 @brief Get the size of the l-vector for a `CeedElemRestriction` 1448 1449 @param[in] rstr `CeedElemRestriction` 1450 @param[out] l_size Variable to store number of nodes 1451 1452 @return An error code: 0 - success, otherwise - failure 1453 1454 @ref Advanced 1455 **/ 1456 int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, CeedSize *l_size) { 1457 *l_size = rstr->l_size; 1458 return CEED_ERROR_SUCCESS; 1459 } 1460 1461 /** 1462 @brief Get the number of components in the elements of a `CeedElemRestriction` 1463 1464 @param[in] rstr `CeedElemRestriction` 1465 @param[out] num_comp Variable to store number of components 1466 1467 @return An error code: 0 - success, otherwise - failure 1468 1469 @ref Advanced 1470 **/ 1471 int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, CeedInt *num_comp) { 1472 *num_comp = rstr->num_comp; 1473 return CEED_ERROR_SUCCESS; 1474 } 1475 1476 /** 1477 @brief Get the number of blocks in a `CeedElemRestriction` 1478 1479 @param[in] rstr `CeedElemRestriction` 1480 @param[out] num_block Variable to store number of blocks 1481 1482 @return An error code: 0 - success, otherwise - failure 1483 1484 @ref Advanced 1485 **/ 1486 int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, CeedInt *num_block) { 1487 *num_block = rstr->num_block; 1488 return CEED_ERROR_SUCCESS; 1489 } 1490 1491 /** 1492 @brief Get the size of blocks in the `CeedElemRestriction` 1493 1494 @param[in] rstr `CeedElemRestriction` 1495 @param[out] block_size Variable to store size of blocks 1496 1497 @return An error code: 0 - success, otherwise - failure 1498 1499 @ref Advanced 1500 **/ 1501 int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, CeedInt *block_size) { 1502 *block_size = rstr->block_size; 1503 return CEED_ERROR_SUCCESS; 1504 } 1505 1506 /** 1507 @brief Get the multiplicity of nodes in a `CeedElemRestriction` 1508 1509 @param[in] rstr `CeedElemRestriction` 1510 @param[out] mult Vector to store multiplicity (of size `l_size`) 1511 1512 @return An error code: 0 - success, otherwise - failure 1513 1514 @ref User 1515 **/ 1516 int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, CeedVector mult) { 1517 CeedVector e_vec; 1518 1519 // Create e_vec to hold intermediate computation in E^T (E 1) 1520 CeedCall(CeedElemRestrictionCreateVector(rstr, NULL, &e_vec)); 1521 1522 // Compute e_vec = E * 1 1523 CeedCall(CeedVectorSetValue(mult, 1.0)); 1524 CeedCall(CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, CEED_REQUEST_IMMEDIATE)); 1525 // Compute multiplicity, mult = E^T * e_vec = E^T (E 1) 1526 CeedCall(CeedVectorSetValue(mult, 0.0)); 1527 CeedCall(CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, CEED_REQUEST_IMMEDIATE)); 1528 // Cleanup 1529 CeedCall(CeedVectorDestroy(&e_vec)); 1530 return CEED_ERROR_SUCCESS; 1531 } 1532 1533 /** 1534 @brief View a `CeedElemRestriction` 1535 1536 @param[in] rstr `CeedElemRestriction` to view 1537 @param[in] stream Stream to write; typically `stdout` or a file 1538 1539 @return Error code: 0 - success, otherwise - failure 1540 1541 @ref User 1542 **/ 1543 int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) { 1544 CeedRestrictionType rstr_type; 1545 1546 CeedCall(CeedElemRestrictionGetType(rstr, &rstr_type)); 1547 1548 if (rstr_type == CEED_RESTRICTION_POINTS) { 1549 CeedInt max_points; 1550 1551 CeedCall(CeedElemRestrictionGetMaxPointsInElement(rstr, &max_points)); 1552 fprintf(stream, 1553 "CeedElemRestriction at points from (%td, %" CeedInt_FMT ") to %" CeedInt_FMT " elements with a maximum of %" CeedInt_FMT 1554 " points on an element\n", 1555 rstr->l_size, rstr->num_comp, rstr->num_elem, max_points); 1556 } else { 1557 char stridesstr[500]; 1558 1559 if (rstr->strides) { 1560 sprintf(stridesstr, "[%" CeedInt_FMT ", %" CeedInt_FMT ", %" CeedInt_FMT "]", rstr->strides[0], rstr->strides[1], rstr->strides[2]); 1561 } else { 1562 sprintf(stridesstr, "%" CeedInt_FMT, rstr->comp_stride); 1563 } 1564 fprintf(stream, "%sCeedElemRestriction from (%td, %" CeedInt_FMT ") to %" CeedInt_FMT " elements with %" CeedInt_FMT " nodes each and %s %s\n", 1565 rstr->block_size > 1 ? "Blocked " : "", rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size, 1566 rstr->strides ? "strides" : "component stride", stridesstr); 1567 } 1568 return CEED_ERROR_SUCCESS; 1569 } 1570 1571 /** 1572 @brief Destroy a `CeedElemRestriction` 1573 1574 @param[in,out] rstr `CeedElemRestriction` to destroy 1575 1576 @return An error code: 0 - success, otherwise - failure 1577 1578 @ref User 1579 **/ 1580 int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) { 1581 if (!*rstr || *rstr == CEED_ELEMRESTRICTION_NONE || --(*rstr)->ref_count > 0) { 1582 *rstr = NULL; 1583 return CEED_ERROR_SUCCESS; 1584 } 1585 CeedCheck((*rstr)->num_readers == 0, (*rstr)->ceed, CEED_ERROR_ACCESS, 1586 "Cannot destroy CeedElemRestriction, a process has read access to the offset data"); 1587 1588 // Only destroy backend data once between rstr and unsigned copy 1589 if ((*rstr)->rstr_base) CeedCall(CeedElemRestrictionDestroy(&(*rstr)->rstr_base)); 1590 else if ((*rstr)->Destroy) CeedCall((*rstr)->Destroy(*rstr)); 1591 1592 CeedCall(CeedFree(&(*rstr)->strides)); 1593 CeedCall(CeedDestroy(&(*rstr)->ceed)); 1594 CeedCall(CeedFree(rstr)); 1595 return CEED_ERROR_SUCCESS; 1596 } 1597 1598 /// @} 1599