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/ceed.h> 9 #include <ceed/backend.h> 10 #include <ceed-impl.h> 11 #include <stdbool.h> 12 #include <stdio.h> 13 14 /// @file 15 /// Implementation of CeedElemRestriction interfaces 16 17 /// ---------------------------------------------------------------------------- 18 /// CeedElemRestriction Library Internal Functions 19 /// ---------------------------------------------------------------------------- 20 /// @addtogroup CeedElemRestrictionDeveloper 21 /// @{ 22 23 /** 24 @brief Permute and pad offsets for a blocked restriction 25 26 @param offsets Array of shape [@a num_elem, @a elem_size]. Row i holds the 27 ordered list of the offsets (into the input CeedVector) 28 for the unknowns corresponding to element i, where 29 0 <= i < @a num_elem. All offsets must be in the range 30 [0, @a l_size - 1]. 31 @param blk_offsets Array of permuted and padded offsets of 32 shape [@a num_blk, @a elem_size, @a blk_size]. 33 @param num_blk Number of blocks 34 @param num_elem Number of elements 35 @param blk_size Number of elements in a block 36 @param elem_size Size of each element 37 38 @return An error code: 0 - success, otherwise - failure 39 40 @ref Utility 41 **/ 42 int CeedPermutePadOffsets(const CeedInt *offsets, CeedInt *blk_offsets, 43 CeedInt num_blk, CeedInt num_elem, CeedInt blk_size, 44 CeedInt elem_size) { 45 for (CeedInt e=0; e<num_blk*blk_size; e+=blk_size) 46 for (int j=0; j<blk_size; j++) 47 for (int k=0; k<elem_size; k++) 48 blk_offsets[e*elem_size + k*blk_size + j] 49 = offsets[CeedIntMin(e+j,num_elem-1)*elem_size + k]; 50 return CEED_ERROR_SUCCESS; 51 } 52 53 /// @} 54 55 /// ---------------------------------------------------------------------------- 56 /// CeedElemRestriction Backend API 57 /// ---------------------------------------------------------------------------- 58 /// @addtogroup CeedElemRestrictionBackend 59 /// @{ 60 61 /** 62 63 @brief Get the strides of a strided CeedElemRestriction 64 65 @param rstr CeedElemRestriction 66 @param[out] strides Variable to store strides array 67 68 @return An error code: 0 - success, otherwise - failure 69 70 @ref Backend 71 **/ 72 int CeedElemRestrictionGetStrides(CeedElemRestriction rstr, 73 CeedInt (*strides)[3]) { 74 if (!rstr->strides) 75 // LCOV_EXCL_START 76 return CeedError(rstr->ceed, CEED_ERROR_MINOR, 77 "ElemRestriction has no stride data"); 78 // LCOV_EXCL_STOP 79 80 for (int i=0; i<3; i++) 81 (*strides)[i] = rstr->strides[i]; 82 return CEED_ERROR_SUCCESS; 83 } 84 85 /** 86 @brief Get read-only access to a CeedElemRestriction offsets array by memtype 87 88 @param rstr CeedElemRestriction to retrieve offsets 89 @param mem_type Memory type on which to access the array. If the backend 90 uses a different memory type, this will perform a copy 91 (possibly cached). 92 @param[out] offsets Array on memory type mem_type 93 94 @return An error code: 0 - success, otherwise - failure 95 96 @ref User 97 **/ 98 int CeedElemRestrictionGetOffsets(CeedElemRestriction rstr, 99 CeedMemType mem_type, 100 const CeedInt **offsets) { 101 int ierr; 102 103 if (!rstr->GetOffsets) 104 // LCOV_EXCL_START 105 return CeedError(rstr->ceed, CEED_ERROR_UNSUPPORTED, 106 "Backend does not support GetOffsets"); 107 // LCOV_EXCL_STOP 108 109 ierr = rstr->GetOffsets(rstr, mem_type, offsets); CeedChk(ierr); 110 rstr->num_readers++; 111 return CEED_ERROR_SUCCESS; 112 } 113 114 /** 115 @brief Restore an offsets array obtained using CeedElemRestrictionGetOffsets() 116 117 @param rstr CeedElemRestriction to restore 118 @param offsets Array of offset data 119 120 @return An error code: 0 - success, otherwise - failure 121 122 @ref User 123 **/ 124 int CeedElemRestrictionRestoreOffsets(CeedElemRestriction rstr, 125 const CeedInt **offsets) { 126 *offsets = NULL; 127 rstr->num_readers--; 128 return CEED_ERROR_SUCCESS; 129 } 130 131 /** 132 @brief Get the strided status of a CeedElemRestriction 133 134 @param rstr CeedElemRestriction 135 @param[out] is_strided Variable to store strided status, 1 if strided else 0 136 137 @return An error code: 0 - success, otherwise - failure 138 139 @ref Backend 140 **/ 141 int CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *is_strided) { 142 *is_strided = rstr->strides ? true : false; 143 return CEED_ERROR_SUCCESS; 144 } 145 146 /** 147 @brief Get oriented status of a CeedElemRestriction 148 149 @param rstr CeedElemRestriction 150 @param[out] is_oriented Variable to store oriented status, 1 if oriented else 0 151 152 @return An error code: 0 - success, otherwise - failure 153 154 @ref Backend 155 **/ 156 int CeedElemRestrictionIsOriented(CeedElemRestriction rstr, bool *is_oriented) { 157 *is_oriented = rstr->is_oriented; 158 return CEED_ERROR_SUCCESS; 159 } 160 161 /** 162 @brief Get the backend stride status of a CeedElemRestriction 163 164 @param rstr CeedElemRestriction 165 @param[out] has_backend_strides Variable to store stride status 166 167 @return An error code: 0 - success, otherwise - failure 168 169 @ref Backend 170 **/ 171 int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, 172 bool *has_backend_strides) { 173 if (!rstr->strides) 174 // LCOV_EXCL_START 175 return CeedError(rstr->ceed, CEED_ERROR_MINOR, 176 "ElemRestriction has no stride data"); 177 // LCOV_EXCL_STOP 178 179 *has_backend_strides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && 180 (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) && 181 (rstr->strides[2] == CEED_STRIDES_BACKEND[2])); 182 return CEED_ERROR_SUCCESS; 183 } 184 185 /** 186 187 @brief Get the E-vector layout of a CeedElemRestriction 188 189 @param rstr CeedElemRestriction 190 @param[out] layout Variable to store layout array, 191 stored as [nodes, components, elements]. 192 The data for node i, component j, element k in the 193 E-vector is given by 194 i*layout[0] + j*layout[1] + k*layout[2] 195 196 @return An error code: 0 - success, otherwise - failure 197 198 @ref Backend 199 **/ 200 int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, 201 CeedInt (*layout)[3]) { 202 if (!rstr->layout[0]) 203 // LCOV_EXCL_START 204 return CeedError(rstr->ceed, CEED_ERROR_MINOR, 205 "ElemRestriction has no layout data"); 206 // LCOV_EXCL_STOP 207 208 for (int i=0; i<3; i++) 209 (*layout)[i] = rstr->layout[i]; 210 return CEED_ERROR_SUCCESS; 211 } 212 213 /** 214 215 @brief Set the E-vector layout of a CeedElemRestriction 216 217 @param rstr CeedElemRestriction 218 @param layout Variable to containing layout array, 219 stored as [nodes, components, elements]. 220 The data for node i, component j, element k in the 221 E-vector is given by 222 i*layout[0] + j*layout[1] + k*layout[2] 223 224 @return An error code: 0 - success, otherwise - failure 225 226 @ref Backend 227 **/ 228 int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, 229 CeedInt layout[3]) { 230 for (int i = 0; i<3; i++) 231 rstr->layout[i] = layout[i]; 232 return CEED_ERROR_SUCCESS; 233 } 234 235 /** 236 @brief Get the backend data of a CeedElemRestriction 237 238 @param rstr CeedElemRestriction 239 @param[out] data Variable to store data 240 241 @return An error code: 0 - success, otherwise - failure 242 243 @ref Backend 244 **/ 245 int CeedElemRestrictionGetData(CeedElemRestriction rstr, void *data) { 246 *(void **)data = rstr->data; 247 return CEED_ERROR_SUCCESS; 248 } 249 250 /** 251 @brief Set the backend data of a CeedElemRestriction 252 253 @param[out] rstr CeedElemRestriction 254 @param data Data to set 255 256 @return An error code: 0 - success, otherwise - failure 257 258 @ref Backend 259 **/ 260 int CeedElemRestrictionSetData(CeedElemRestriction rstr, void *data) { 261 rstr->data = data; 262 return CEED_ERROR_SUCCESS; 263 } 264 265 /** 266 @brief Increment the reference counter for a CeedElemRestriction 267 268 @param rstr ElemRestriction to increment the reference counter 269 270 @return An error code: 0 - success, otherwise - failure 271 272 @ref Backend 273 **/ 274 int CeedElemRestrictionReference(CeedElemRestriction rstr) { 275 rstr->ref_count++; 276 return CEED_ERROR_SUCCESS; 277 } 278 279 /// @} 280 281 /// @cond DOXYGEN_SKIP 282 static struct CeedElemRestriction_private ceed_elemrestriction_none; 283 /// @endcond 284 285 /// ---------------------------------------------------------------------------- 286 /// CeedElemRestriction Public API 287 /// ---------------------------------------------------------------------------- 288 /// @addtogroup CeedElemRestrictionUser 289 /// @{ 290 291 /// Indicate that the stride is determined by the backend 292 const CeedInt CEED_STRIDES_BACKEND[3] = {0}; 293 294 /// Indicate that no CeedElemRestriction is provided by the user 295 const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = 296 &ceed_elemrestriction_none; 297 298 /** 299 @brief Create a CeedElemRestriction 300 301 @param ceed A Ceed object where the CeedElemRestriction will be created 302 @param num_elem Number of elements described in the @a offsets array 303 @param elem_size Size (number of "nodes") per element 304 @param num_comp Number of field components per interpolation node 305 (1 for scalar fields) 306 @param comp_stride Stride between components for the same L-vector "node". 307 Data for node i, component j, element k can be found in 308 the L-vector at index 309 offsets[i + k*elem_size] + j*comp_stride. 310 @param l_size The size of the L-vector. This vector may be larger than 311 the elements and fields given by this restriction. 312 @param mem_type Memory type of the @a offsets array, see CeedMemType 313 @param copy_mode Copy mode for the @a offsets array, see CeedCopyMode 314 @param offsets Array of shape [@a num_elem, @a elem_size]. Row i holds the 315 ordered list of the offsets (into the input CeedVector) 316 for the unknowns corresponding to element i, where 317 0 <= i < @a num_elem. All offsets must be in the range 318 [0, @a l_size - 1]. 319 @param[out] rstr Address of the variable where the newly created 320 CeedElemRestriction will be stored 321 322 @return An error code: 0 - success, otherwise - failure 323 324 @ref User 325 **/ 326 int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, 327 CeedInt num_comp, CeedInt comp_stride, 328 CeedSize l_size, CeedMemType mem_type, 329 CeedCopyMode copy_mode, const CeedInt *offsets, 330 CeedElemRestriction *rstr) { 331 int ierr; 332 333 if (!ceed->ElemRestrictionCreate) { 334 Ceed delegate; 335 ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"); 336 CeedChk(ierr); 337 338 if (!delegate) 339 // LCOV_EXCL_START 340 return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 341 "Backend does not support ElemRestrictionCreate"); 342 // LCOV_EXCL_STOP 343 344 ierr = CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, 345 comp_stride, l_size, mem_type, copy_mode, 346 offsets, rstr); CeedChk(ierr); 347 return CEED_ERROR_SUCCESS; 348 } 349 350 ierr = CeedCalloc(1, rstr); CeedChk(ierr); 351 (*rstr)->ceed = ceed; 352 ierr = CeedReference(ceed); CeedChk(ierr); 353 (*rstr)->ref_count = 1; 354 (*rstr)->num_elem = num_elem; 355 (*rstr)->elem_size = elem_size; 356 (*rstr)->num_comp = num_comp; 357 (*rstr)->comp_stride = comp_stride; 358 (*rstr)->l_size = l_size; 359 (*rstr)->num_blk = num_elem; 360 (*rstr)->blk_size = 1; 361 (*rstr)->is_oriented = 0; 362 ierr = ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, *rstr); 363 CeedChk(ierr); 364 return CEED_ERROR_SUCCESS; 365 } 366 367 /** 368 @brief Create a CeedElemRestriction with orientation sign 369 370 @param ceed A Ceed object where the CeedElemRestriction will be created 371 @param num_elem Number of elements described in the @a offsets array 372 @param elem_size Size (number of "nodes") per element 373 @param num_comp Number of field components per interpolation node 374 (1 for scalar fields) 375 @param comp_stride Stride between components for the same L-vector "node". 376 Data for node i, component j, element k can be found in 377 the L-vector at index 378 offsets[i + k*elem_size] + j*comp_stride. 379 @param l_size The size of the L-vector. This vector may be larger than 380 the elements and fields given by this restriction. 381 @param mem_type Memory type of the @a offsets array, see CeedMemType 382 @param copy_mode Copy mode for the @a offsets array, see CeedCopyMode 383 @param offsets Array of shape [@a num_elem, @a elem_size]. Row i holds the 384 ordered list of the offsets (into the input CeedVector) 385 for the unknowns corresponding to element i, where 386 0 <= i < @a num_elem. All offsets must be in the range 387 [0, @a l_size - 1]. 388 @param orient Array of shape [@a num_elem, @a elem_size] with bool false 389 for positively oriented and true to flip the orientation. 390 @param[out] rstr Address of the variable where the newly created 391 CeedElemRestriction will be stored 392 393 @return An error code: 0 - success, otherwise - failure 394 395 @ref User 396 **/ 397 int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, 398 CeedInt elem_size, CeedInt num_comp, 399 CeedInt comp_stride, CeedSize l_size, 400 CeedMemType mem_type, CeedCopyMode copy_mode, 401 const CeedInt *offsets, const bool *orient, 402 CeedElemRestriction *rstr) { 403 int ierr; 404 405 if (!ceed->ElemRestrictionCreateOriented) { 406 Ceed delegate; 407 ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"); 408 CeedChk(ierr); 409 410 if (!delegate) 411 // LCOV_EXCL_START 412 return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 413 "Backend does not implement ElemRestrictionCreateOriented"); 414 // LCOV_EXCL_STOP 415 416 ierr = CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, 417 num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, 418 orient, rstr); CeedChk(ierr); 419 return CEED_ERROR_SUCCESS; 420 } 421 422 ierr = CeedCalloc(1, rstr); CeedChk(ierr); 423 (*rstr)->ceed = ceed; 424 ierr = CeedReference(ceed); CeedChk(ierr); 425 (*rstr)->ref_count = 1; 426 (*rstr)->num_elem = num_elem; 427 (*rstr)->elem_size = elem_size; 428 (*rstr)->num_comp = num_comp; 429 (*rstr)->comp_stride = comp_stride; 430 (*rstr)->l_size = l_size; 431 (*rstr)->num_blk = num_elem; 432 (*rstr)->blk_size = 1; 433 (*rstr)->is_oriented = 1; 434 ierr = ceed->ElemRestrictionCreateOriented(mem_type, copy_mode, 435 offsets, orient, *rstr); CeedChk(ierr); 436 return CEED_ERROR_SUCCESS; 437 } 438 439 /** 440 @brief Create a strided CeedElemRestriction 441 442 @param ceed A Ceed object where the CeedElemRestriction will be created 443 @param num_elem Number of elements described by the restriction 444 @param elem_size Size (number of "nodes") per element 445 @param num_comp Number of field components per interpolation "node" 446 (1 for scalar fields) 447 @param l_size The size of the L-vector. This vector may be larger than 448 the elements and fields given by this restriction. 449 @param strides Array for strides between [nodes, components, elements]. 450 Data for node i, component j, element k can be found in 451 the L-vector at index 452 i*strides[0] + j*strides[1] + k*strides[2]. 453 @a CEED_STRIDES_BACKEND may be used with vectors created 454 by a Ceed backend. 455 @param rstr Address of the variable where the newly created 456 CeedElemRestriction will be stored 457 458 @return An error code: 0 - success, otherwise - failure 459 460 @ref User 461 **/ 462 int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, 463 CeedInt elem_size, 464 CeedInt num_comp, CeedSize l_size, 465 const CeedInt strides[3], 466 CeedElemRestriction *rstr) { 467 int ierr; 468 469 if (!ceed->ElemRestrictionCreate) { 470 Ceed delegate; 471 ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"); 472 CeedChk(ierr); 473 474 if (!delegate) 475 // LCOV_EXCL_START 476 return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 477 "Backend does not support ElemRestrictionCreate"); 478 // LCOV_EXCL_STOP 479 480 ierr = CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, 481 l_size, strides, rstr); 482 CeedChk(ierr); 483 return CEED_ERROR_SUCCESS; 484 } 485 486 ierr = CeedCalloc(1, rstr); CeedChk(ierr); 487 (*rstr)->ceed = ceed; 488 ierr = CeedReference(ceed); CeedChk(ierr); 489 (*rstr)->ref_count = 1; 490 (*rstr)->num_elem = num_elem; 491 (*rstr)->elem_size = elem_size; 492 (*rstr)->num_comp = num_comp; 493 (*rstr)->l_size = l_size; 494 (*rstr)->num_blk = num_elem; 495 (*rstr)->blk_size = 1; 496 (*rstr)->is_oriented = 0; 497 ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr); 498 for (int i=0; i<3; i++) 499 (*rstr)->strides[i] = strides[i]; 500 ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, 501 *rstr); 502 CeedChk(ierr); 503 return CEED_ERROR_SUCCESS; 504 } 505 506 /** 507 @brief Create a blocked CeedElemRestriction, typically only called by backends 508 509 @param ceed A Ceed object where the CeedElemRestriction will be created. 510 @param num_elem Number of elements described in the @a offsets array. 511 @param elem_size Size (number of unknowns) per element 512 @param blk_size Number of elements in a block 513 @param num_comp Number of field components per interpolation node 514 (1 for scalar fields) 515 @param comp_stride Stride between components for the same L-vector "node". 516 Data for node i, component j, element k can be found in 517 the L-vector at index 518 offsets[i + k*elem_size] + j*comp_stride. 519 @param l_size The size of the L-vector. This vector may be larger than 520 the elements and fields given by this restriction. 521 @param mem_type Memory type of the @a offsets array, see CeedMemType 522 @param copy_mode Copy mode for the @a offsets array, see CeedCopyMode 523 @param offsets Array of shape [@a num_elem, @a elem_size]. Row i holds the 524 ordered list of the offsets (into the input CeedVector) 525 for the unknowns corresponding to element i, where 526 0 <= i < @a num_elem. All offsets must be in the range 527 [0, @a l_size - 1]. The backend will permute and pad this 528 array to the desired ordering for the blocksize, which is 529 typically given by the backend. The default reordering is 530 to interlace elements. 531 @param rstr Address of the variable where the newly created 532 CeedElemRestriction will be stored 533 534 @return An error code: 0 - success, otherwise - failure 535 536 @ref Backend 537 **/ 538 int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, 539 CeedInt elem_size, 540 CeedInt blk_size, CeedInt num_comp, 541 CeedInt comp_stride, CeedSize l_size, 542 CeedMemType mem_type, CeedCopyMode copy_mode, 543 const CeedInt *offsets, 544 CeedElemRestriction *rstr) { 545 int ierr; 546 CeedInt *blk_offsets; 547 CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size); 548 549 if (!ceed->ElemRestrictionCreateBlocked) { 550 Ceed delegate; 551 ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"); 552 CeedChk(ierr); 553 554 if (!delegate) 555 // LCOV_EXCL_START 556 return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support " 557 "ElemRestrictionCreateBlocked"); 558 // LCOV_EXCL_STOP 559 560 ierr = CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, blk_size, 561 num_comp, comp_stride, l_size, mem_type, 562 copy_mode, offsets, rstr); 563 CeedChk(ierr); 564 return CEED_ERROR_SUCCESS; 565 } 566 567 ierr = CeedCalloc(1, rstr); CeedChk(ierr); 568 569 ierr = CeedCalloc(num_blk*blk_size*elem_size, &blk_offsets); CeedChk(ierr); 570 ierr = CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size, 571 elem_size); CeedChk(ierr); 572 573 (*rstr)->ceed = ceed; 574 ierr = CeedReference(ceed); CeedChk(ierr); 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)->num_blk = num_blk; 582 (*rstr)->blk_size = blk_size; 583 (*rstr)->is_oriented = 0; 584 ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, 585 (const CeedInt *) blk_offsets, *rstr); CeedChk(ierr); 586 if (copy_mode == CEED_OWN_POINTER) { 587 ierr = CeedFree(&offsets); CeedChk(ierr); 588 } 589 return CEED_ERROR_SUCCESS; 590 } 591 592 /** 593 @brief Create a blocked strided CeedElemRestriction 594 595 @param ceed A Ceed object where the CeedElemRestriction will be created 596 @param num_elem Number of elements described by the restriction 597 @param elem_size Size (number of "nodes") per element 598 @param blk_size Number of elements in a block 599 @param num_comp Number of field components per interpolation node 600 (1 for scalar fields) 601 @param l_size The size of the L-vector. This vector may be larger than 602 the elements and fields given by this restriction. 603 @param strides Array for strides between [nodes, components, elements]. 604 Data for node i, component j, element k can be found in 605 the L-vector at index 606 i*strides[0] + j*strides[1] + k*strides[2]. 607 @a CEED_STRIDES_BACKEND may be used with vectors created 608 by a Ceed backend. 609 @param rstr Address of the variable where the newly created 610 CeedElemRestriction will be stored 611 612 @return An error code: 0 - success, otherwise - failure 613 614 @ref User 615 **/ 616 int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, 617 CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedSize l_size, 618 const CeedInt strides[3], CeedElemRestriction *rstr) { 619 int ierr; 620 CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size); 621 622 if (!ceed->ElemRestrictionCreateBlocked) { 623 Ceed delegate; 624 ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"); 625 CeedChk(ierr); 626 627 if (!delegate) 628 // LCOV_EXCL_START 629 return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support " 630 "ElemRestrictionCreateBlocked"); 631 // LCOV_EXCL_STOP 632 633 ierr = CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, 634 blk_size, num_comp, l_size, strides, rstr); CeedChk(ierr); 635 return CEED_ERROR_SUCCESS; 636 } 637 638 ierr = CeedCalloc(1, rstr); CeedChk(ierr); 639 640 (*rstr)->ceed = ceed; 641 ierr = CeedReference(ceed); CeedChk(ierr); 642 (*rstr)->ref_count = 1; 643 (*rstr)->num_elem = num_elem; 644 (*rstr)->elem_size = elem_size; 645 (*rstr)->num_comp = num_comp; 646 (*rstr)->l_size = l_size; 647 (*rstr)->num_blk = num_blk; 648 (*rstr)->blk_size = blk_size; 649 (*rstr)->is_oriented = 0; 650 ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr); 651 for (int i=0; i<3; i++) 652 (*rstr)->strides[i] = strides[i]; 653 ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, 654 NULL, *rstr); CeedChk(ierr); 655 return CEED_ERROR_SUCCESS; 656 } 657 658 /** 659 @brief Copy the pointer to a CeedElemRestriction. Both pointers should 660 be destroyed with `CeedElemRestrictionDestroy()`; 661 Note: If `*rstr_copy` is non-NULL, then it is assumed that 662 `*rstr_copy` is a pointer to a CeedElemRestriction. This 663 CeedElemRestriction will be destroyed if `*rstr_copy` is the 664 only reference to this CeedElemRestriction. 665 666 @param rstr CeedElemRestriction to copy reference to 667 @param[out] rstr_copy Variable to store copied reference 668 669 @return An error code: 0 - success, otherwise - failure 670 671 @ref User 672 **/ 673 int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, 674 CeedElemRestriction *rstr_copy) { 675 int ierr; 676 677 ierr = CeedElemRestrictionReference(rstr); CeedChk(ierr); 678 ierr = CeedElemRestrictionDestroy(rstr_copy); CeedChk(ierr); 679 *rstr_copy = rstr; 680 return CEED_ERROR_SUCCESS; 681 } 682 683 /** 684 @brief Create CeedVectors associated with a CeedElemRestriction 685 686 @param rstr CeedElemRestriction 687 @param l_vec The address of the L-vector to be created, or NULL 688 @param e_vec The address of the E-vector to be created, or NULL 689 690 @return An error code: 0 - success, otherwise - failure 691 692 @ref User 693 **/ 694 int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, 695 CeedVector *e_vec) { 696 int ierr; 697 CeedInt e_size, l_size; 698 l_size = rstr->l_size; 699 e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp; 700 if (l_vec) { 701 ierr = CeedVectorCreate(rstr->ceed, l_size, l_vec); CeedChk(ierr); 702 } 703 if (e_vec) { 704 ierr = CeedVectorCreate(rstr->ceed, e_size, e_vec); CeedChk(ierr); 705 } 706 return CEED_ERROR_SUCCESS; 707 } 708 709 /** 710 @brief Restrict an L-vector to an E-vector or apply its transpose 711 712 @param rstr CeedElemRestriction 713 @param t_mode Apply restriction or transpose 714 @param u Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE) 715 @param ru Output vector (of shape [@a num_elem * @a elem_size] when 716 t_mode=@ref CEED_NOTRANSPOSE). Ordering of the e-vector is decided 717 by the backend. 718 @param request Request or @ref CEED_REQUEST_IMMEDIATE 719 720 @return An error code: 0 - success, otherwise - failure 721 722 @ref User 723 **/ 724 int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, 725 CeedVector u, CeedVector ru, 726 CeedRequest *request) { 727 CeedInt m, n; 728 int ierr; 729 730 if (t_mode == CEED_NOTRANSPOSE) { 731 m = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp; 732 n = rstr->l_size; 733 } else { 734 m = rstr->l_size; 735 n = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp; 736 } 737 if (n != u->length) 738 // LCOV_EXCL_START 739 return CeedError(rstr->ceed, CEED_ERROR_DIMENSION, 740 "Input vector size %d not compatible with " 741 "element restriction (%d, %d)", u->length, m, n); 742 // LCOV_EXCL_STOP 743 if (m != ru->length) 744 // LCOV_EXCL_START 745 return CeedError(rstr->ceed, CEED_ERROR_DIMENSION, 746 "Output vector size %d not compatible with " 747 "element restriction (%d, %d)", ru->length, m, n); 748 // LCOV_EXCL_STOP 749 ierr = rstr->Apply(rstr, t_mode, u, ru, request); CeedChk(ierr); 750 return CEED_ERROR_SUCCESS; 751 } 752 753 /** 754 @brief Restrict an L-vector to a block of an E-vector or apply its transpose 755 756 @param rstr CeedElemRestriction 757 @param block Block number to restrict to/from, i.e. block=0 will handle 758 elements [0 : blk_size] and block=3 will handle elements 759 [3*blk_size : 4*blk_size] 760 @param t_mode Apply restriction or transpose 761 @param u Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE) 762 @param ru Output vector (of shape [@a blk_size * @a elem_size] when 763 t_mode=@ref CEED_NOTRANSPOSE). Ordering of the e-vector is decided 764 by the backend. 765 @param request Request or @ref CEED_REQUEST_IMMEDIATE 766 767 @return An error code: 0 - success, otherwise - failure 768 769 @ref Backend 770 **/ 771 int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, 772 CeedTransposeMode t_mode, CeedVector u, 773 CeedVector ru, CeedRequest *request) { 774 CeedInt m, n; 775 int ierr; 776 777 if (t_mode == CEED_NOTRANSPOSE) { 778 m = rstr->blk_size * rstr->elem_size * rstr->num_comp; 779 n = rstr->l_size; 780 } else { 781 m = rstr->l_size; 782 n = rstr->blk_size * rstr->elem_size * rstr->num_comp; 783 } 784 if (n != u->length) 785 // LCOV_EXCL_START 786 return CeedError(rstr->ceed, CEED_ERROR_DIMENSION, 787 "Input vector size %d not compatible with " 788 "element restriction (%d, %d)", u->length, m, n); 789 // LCOV_EXCL_STOP 790 if (m != ru->length) 791 // LCOV_EXCL_START 792 return CeedError(rstr->ceed, CEED_ERROR_DIMENSION, 793 "Output vector size %d not compatible with " 794 "element restriction (%d, %d)", ru->length, m, n); 795 // LCOV_EXCL_STOP 796 if (rstr->blk_size*block > rstr->num_elem) 797 // LCOV_EXCL_START 798 return CeedError(rstr->ceed, CEED_ERROR_DIMENSION, 799 "Cannot retrieve block %d, element %d > " 800 "total elements %d", block, rstr->blk_size*block, 801 rstr->num_elem); 802 // LCOV_EXCL_STOP 803 ierr = rstr->ApplyBlock(rstr, block, t_mode, u, ru, request); 804 CeedChk(ierr); 805 return CEED_ERROR_SUCCESS; 806 } 807 808 /** 809 @brief Get the Ceed associated with a CeedElemRestriction 810 811 @param rstr CeedElemRestriction 812 @param[out] ceed Variable to store Ceed 813 814 @return An error code: 0 - success, otherwise - failure 815 816 @ref Advanced 817 **/ 818 int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) { 819 *ceed = rstr->ceed; 820 return CEED_ERROR_SUCCESS; 821 } 822 823 /** 824 @brief Get the L-vector component stride 825 826 @param rstr CeedElemRestriction 827 @param[out] comp_stride Variable to store component stride 828 829 @return An error code: 0 - success, otherwise - failure 830 831 @ref Advanced 832 **/ 833 int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, 834 CeedInt *comp_stride) { 835 *comp_stride = rstr->comp_stride; 836 return CEED_ERROR_SUCCESS; 837 } 838 839 /** 840 @brief Get the total number of elements in the range of a CeedElemRestriction 841 842 @param rstr CeedElemRestriction 843 @param[out] num_elem Variable to store number of elements 844 845 @return An error code: 0 - success, otherwise - failure 846 847 @ref Advanced 848 **/ 849 int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, 850 CeedInt *num_elem) { 851 *num_elem = rstr->num_elem; 852 return CEED_ERROR_SUCCESS; 853 } 854 855 /** 856 @brief Get the size of elements in the CeedElemRestriction 857 858 @param rstr CeedElemRestriction 859 @param[out] elem_size Variable to store size of elements 860 861 @return An error code: 0 - success, otherwise - failure 862 863 @ref Advanced 864 **/ 865 int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, 866 CeedInt *elem_size) { 867 *elem_size = rstr->elem_size; 868 return CEED_ERROR_SUCCESS; 869 } 870 871 /** 872 @brief Get the size of the l-vector for a CeedElemRestriction 873 874 @param rstr CeedElemRestriction 875 @param[out] l_size Variable to store number of nodes 876 877 @return An error code: 0 - success, otherwise - failure 878 879 @ref Advanced 880 **/ 881 int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, 882 CeedSize *l_size) { 883 *l_size = rstr->l_size; 884 return CEED_ERROR_SUCCESS; 885 } 886 887 /** 888 @brief Get the number of components in the elements of a 889 CeedElemRestriction 890 891 @param rstr CeedElemRestriction 892 @param[out] num_comp Variable to store number of components 893 894 @return An error code: 0 - success, otherwise - failure 895 896 @ref Advanced 897 **/ 898 int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, 899 CeedInt *num_comp) { 900 *num_comp = rstr->num_comp; 901 return CEED_ERROR_SUCCESS; 902 } 903 904 /** 905 @brief Get the number of blocks in a CeedElemRestriction 906 907 @param rstr CeedElemRestriction 908 @param[out] num_block Variable to store number of blocks 909 910 @return An error code: 0 - success, otherwise - failure 911 912 @ref Advanced 913 **/ 914 int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, 915 CeedInt *num_block) { 916 *num_block = rstr->num_blk; 917 return CEED_ERROR_SUCCESS; 918 } 919 920 /** 921 @brief Get the size of blocks in the CeedElemRestriction 922 923 @param rstr CeedElemRestriction 924 @param[out] blk_size Variable to store size of blocks 925 926 @return An error code: 0 - success, otherwise - failure 927 928 @ref Advanced 929 **/ 930 int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, 931 CeedInt *blk_size) { 932 *blk_size = rstr->blk_size; 933 return CEED_ERROR_SUCCESS; 934 } 935 936 /** 937 @brief Get the multiplicity of nodes in a CeedElemRestriction 938 939 @param rstr CeedElemRestriction 940 @param[out] mult Vector to store multiplicity (of size l_size) 941 942 @return An error code: 0 - success, otherwise - failure 943 944 @ref User 945 **/ 946 int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, 947 CeedVector mult) { 948 int ierr; 949 CeedVector e_vec; 950 951 // Create e_vec to hold intermediate computation in E^T (E 1) 952 ierr = CeedElemRestrictionCreateVector(rstr, NULL, &e_vec); CeedChk(ierr); 953 954 // Compute e_vec = E * 1 955 ierr = CeedVectorSetValue(mult, 1.0); CeedChk(ierr); 956 ierr = CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, 957 CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 958 // Compute multiplicity, mult = E^T * e_vec = E^T (E 1) 959 ierr = CeedVectorSetValue(mult, 0.0); CeedChk(ierr); 960 ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, 961 CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 962 // Cleanup 963 ierr = CeedVectorDestroy(&e_vec); CeedChk(ierr); 964 return CEED_ERROR_SUCCESS; 965 } 966 967 /** 968 @brief View a CeedElemRestriction 969 970 @param[in] rstr CeedElemRestriction to view 971 @param[in] stream Stream to write; typically stdout/stderr or a file 972 973 @return Error code: 0 - success, otherwise - failure 974 975 @ref User 976 **/ 977 int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) { 978 char stridesstr[500]; 979 if (rstr->strides) 980 sprintf(stridesstr, "[%d, %d, %d]", rstr->strides[0], rstr->strides[1], 981 rstr->strides[2]); 982 else 983 sprintf(stridesstr, "%d", rstr->comp_stride); 984 985 fprintf(stream, "%sCeedElemRestriction from (%td, %d) to %d elements with %d " 986 "nodes each and %s %s\n", rstr->blk_size > 1 ? "Blocked " : "", 987 rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size, 988 rstr->strides ? "strides" : "component stride", stridesstr); 989 return CEED_ERROR_SUCCESS; 990 } 991 992 /** 993 @brief Destroy a CeedElemRestriction 994 995 @param rstr CeedElemRestriction to destroy 996 997 @return An error code: 0 - success, otherwise - failure 998 999 @ref User 1000 **/ 1001 int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) { 1002 int ierr; 1003 1004 if (!*rstr || --(*rstr)->ref_count > 0) return CEED_ERROR_SUCCESS; 1005 if ((*rstr)->num_readers) 1006 // LCOV_EXCL_START 1007 return CeedError((*rstr)->ceed, CEED_ERROR_ACCESS, 1008 "Cannot destroy CeedElemRestriction, " 1009 "a process has read access to the offset data"); 1010 // LCOV_EXCL_STOP 1011 if ((*rstr)->Destroy) { 1012 ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr); 1013 } 1014 ierr = CeedFree(&(*rstr)->strides); CeedChk(ierr); 1015 ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr); 1016 ierr = CeedFree(rstr); CeedChk(ierr); 1017 return CEED_ERROR_SUCCESS; 1018 } 1019 1020 /// @} 1021