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 @brief Estimate number of FLOPs required to apply CeedElemRestriction in t_mode 281 282 @param rstr ElemRestriction to estimate FLOPs for 283 @param t_mode Apply restriction or transpose 284 @param flops Address of variable to hold FLOPs estimate 285 286 @ref Backend 287 **/ 288 int CeedElemRestrictionGetFlopsEstimate(CeedElemRestriction rstr, 289 CeedTransposeMode t_mode, CeedSize *flops) { 290 int ierr; 291 bool is_oriented; 292 CeedInt e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * 293 rstr->num_comp, 294 scale = 0; 295 296 ierr = CeedElemRestrictionIsOriented(rstr, &is_oriented); CeedChk(ierr); 297 switch (t_mode) { 298 case CEED_NOTRANSPOSE: scale = is_oriented ? 1 : 0; break; 299 case CEED_TRANSPOSE: scale = is_oriented ? 2 : 1; break; 300 } 301 *flops = e_size * scale; 302 303 return CEED_ERROR_SUCCESS; 304 } 305 306 /// @} 307 308 /// @cond DOXYGEN_SKIP 309 static struct CeedElemRestriction_private ceed_elemrestriction_none; 310 /// @endcond 311 312 /// ---------------------------------------------------------------------------- 313 /// CeedElemRestriction Public API 314 /// ---------------------------------------------------------------------------- 315 /// @addtogroup CeedElemRestrictionUser 316 /// @{ 317 318 /// Indicate that the stride is determined by the backend 319 const CeedInt CEED_STRIDES_BACKEND[3] = {0}; 320 321 /// Indicate that no CeedElemRestriction is provided by the user 322 const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = 323 &ceed_elemrestriction_none; 324 325 /** 326 @brief Create a CeedElemRestriction 327 328 @param ceed A Ceed object where the CeedElemRestriction will be created 329 @param num_elem Number of elements described in the @a offsets array 330 @param elem_size Size (number of "nodes") per element 331 @param num_comp Number of field components per interpolation node 332 (1 for scalar fields) 333 @param comp_stride Stride between components for the same L-vector "node". 334 Data for node i, component j, element k can be found in 335 the L-vector at index 336 offsets[i + k*elem_size] + j*comp_stride. 337 @param l_size The size of the L-vector. This vector may be larger than 338 the elements and fields given by this restriction. 339 @param mem_type Memory type of the @a offsets array, see CeedMemType 340 @param copy_mode Copy mode for the @a offsets array, see CeedCopyMode 341 @param offsets Array of shape [@a num_elem, @a elem_size]. Row i holds the 342 ordered list of the offsets (into the input CeedVector) 343 for the unknowns corresponding to element i, where 344 0 <= i < @a num_elem. All offsets must be in the range 345 [0, @a l_size - 1]. 346 @param[out] rstr Address of the variable where the newly created 347 CeedElemRestriction will be stored 348 349 @return An error code: 0 - success, otherwise - failure 350 351 @ref User 352 **/ 353 int CeedElemRestrictionCreate(Ceed ceed, CeedInt num_elem, CeedInt elem_size, 354 CeedInt num_comp, CeedInt comp_stride, 355 CeedSize l_size, CeedMemType mem_type, 356 CeedCopyMode copy_mode, const CeedInt *offsets, 357 CeedElemRestriction *rstr) { 358 int ierr; 359 360 if (!ceed->ElemRestrictionCreate) { 361 Ceed delegate; 362 ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"); 363 CeedChk(ierr); 364 365 if (!delegate) 366 // LCOV_EXCL_START 367 return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 368 "Backend does not support ElemRestrictionCreate"); 369 // LCOV_EXCL_STOP 370 371 ierr = CeedElemRestrictionCreate(delegate, num_elem, elem_size, num_comp, 372 comp_stride, l_size, mem_type, copy_mode, 373 offsets, rstr); CeedChk(ierr); 374 return CEED_ERROR_SUCCESS; 375 } 376 377 ierr = CeedCalloc(1, rstr); CeedChk(ierr); 378 (*rstr)->ceed = ceed; 379 ierr = CeedReference(ceed); CeedChk(ierr); 380 (*rstr)->ref_count = 1; 381 (*rstr)->num_elem = num_elem; 382 (*rstr)->elem_size = elem_size; 383 (*rstr)->num_comp = num_comp; 384 (*rstr)->comp_stride = comp_stride; 385 (*rstr)->l_size = l_size; 386 (*rstr)->num_blk = num_elem; 387 (*rstr)->blk_size = 1; 388 (*rstr)->is_oriented = 0; 389 ierr = ceed->ElemRestrictionCreate(mem_type, copy_mode, offsets, *rstr); 390 CeedChk(ierr); 391 return CEED_ERROR_SUCCESS; 392 } 393 394 /** 395 @brief Create a CeedElemRestriction with orientation sign 396 397 @param ceed A Ceed object where the CeedElemRestriction will be created 398 @param num_elem Number of elements described in the @a offsets array 399 @param elem_size Size (number of "nodes") per element 400 @param num_comp Number of field components per interpolation node 401 (1 for scalar fields) 402 @param comp_stride Stride between components for the same L-vector "node". 403 Data for node i, component j, element k can be found in 404 the L-vector at index 405 offsets[i + k*elem_size] + j*comp_stride. 406 @param l_size The size of the L-vector. This vector may be larger than 407 the elements and fields given by this restriction. 408 @param mem_type Memory type of the @a offsets array, see CeedMemType 409 @param copy_mode Copy mode for the @a offsets array, see CeedCopyMode 410 @param offsets Array of shape [@a num_elem, @a elem_size]. Row i holds the 411 ordered list of the offsets (into the input CeedVector) 412 for the unknowns corresponding to element i, where 413 0 <= i < @a num_elem. All offsets must be in the range 414 [0, @a l_size - 1]. 415 @param orient Array of shape [@a num_elem, @a elem_size] with bool false 416 for positively oriented and true to flip the orientation. 417 @param[out] rstr Address of the variable where the newly created 418 CeedElemRestriction will be stored 419 420 @return An error code: 0 - success, otherwise - failure 421 422 @ref User 423 **/ 424 int CeedElemRestrictionCreateOriented(Ceed ceed, CeedInt num_elem, 425 CeedInt elem_size, CeedInt num_comp, 426 CeedInt comp_stride, CeedSize l_size, 427 CeedMemType mem_type, CeedCopyMode copy_mode, 428 const CeedInt *offsets, const bool *orient, 429 CeedElemRestriction *rstr) { 430 int ierr; 431 432 if (!ceed->ElemRestrictionCreateOriented) { 433 Ceed delegate; 434 ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"); 435 CeedChk(ierr); 436 437 if (!delegate) 438 // LCOV_EXCL_START 439 return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 440 "Backend does not implement ElemRestrictionCreateOriented"); 441 // LCOV_EXCL_STOP 442 443 ierr = CeedElemRestrictionCreateOriented(delegate, num_elem, elem_size, 444 num_comp, comp_stride, l_size, mem_type, copy_mode, offsets, 445 orient, rstr); CeedChk(ierr); 446 return CEED_ERROR_SUCCESS; 447 } 448 449 ierr = CeedCalloc(1, rstr); CeedChk(ierr); 450 (*rstr)->ceed = ceed; 451 ierr = CeedReference(ceed); CeedChk(ierr); 452 (*rstr)->ref_count = 1; 453 (*rstr)->num_elem = num_elem; 454 (*rstr)->elem_size = elem_size; 455 (*rstr)->num_comp = num_comp; 456 (*rstr)->comp_stride = comp_stride; 457 (*rstr)->l_size = l_size; 458 (*rstr)->num_blk = num_elem; 459 (*rstr)->blk_size = 1; 460 (*rstr)->is_oriented = 1; 461 ierr = ceed->ElemRestrictionCreateOriented(mem_type, copy_mode, 462 offsets, orient, *rstr); CeedChk(ierr); 463 return CEED_ERROR_SUCCESS; 464 } 465 466 /** 467 @brief Create a strided CeedElemRestriction 468 469 @param ceed A Ceed object where the CeedElemRestriction will be created 470 @param num_elem Number of elements described by the restriction 471 @param elem_size Size (number of "nodes") per element 472 @param num_comp Number of field components per interpolation "node" 473 (1 for scalar fields) 474 @param l_size The size of the L-vector. This vector may be larger than 475 the elements and fields given by this restriction. 476 @param strides Array for strides between [nodes, components, elements]. 477 Data for node i, component j, element k can be found in 478 the L-vector at index 479 i*strides[0] + j*strides[1] + k*strides[2]. 480 @a CEED_STRIDES_BACKEND may be used with vectors created 481 by a Ceed backend. 482 @param rstr Address of the variable where the newly created 483 CeedElemRestriction will be stored 484 485 @return An error code: 0 - success, otherwise - failure 486 487 @ref User 488 **/ 489 int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt num_elem, 490 CeedInt elem_size, 491 CeedInt num_comp, CeedSize l_size, 492 const CeedInt strides[3], 493 CeedElemRestriction *rstr) { 494 int ierr; 495 496 if (!ceed->ElemRestrictionCreate) { 497 Ceed delegate; 498 ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"); 499 CeedChk(ierr); 500 501 if (!delegate) 502 // LCOV_EXCL_START 503 return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 504 "Backend does not support ElemRestrictionCreate"); 505 // LCOV_EXCL_STOP 506 507 ierr = CeedElemRestrictionCreateStrided(delegate, num_elem, elem_size, num_comp, 508 l_size, strides, rstr); 509 CeedChk(ierr); 510 return CEED_ERROR_SUCCESS; 511 } 512 513 ierr = CeedCalloc(1, rstr); CeedChk(ierr); 514 (*rstr)->ceed = ceed; 515 ierr = CeedReference(ceed); CeedChk(ierr); 516 (*rstr)->ref_count = 1; 517 (*rstr)->num_elem = num_elem; 518 (*rstr)->elem_size = elem_size; 519 (*rstr)->num_comp = num_comp; 520 (*rstr)->l_size = l_size; 521 (*rstr)->num_blk = num_elem; 522 (*rstr)->blk_size = 1; 523 (*rstr)->is_oriented = 0; 524 ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr); 525 for (int i=0; i<3; i++) 526 (*rstr)->strides[i] = strides[i]; 527 ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, 528 *rstr); 529 CeedChk(ierr); 530 return CEED_ERROR_SUCCESS; 531 } 532 533 /** 534 @brief Create a blocked CeedElemRestriction, typically only called by backends 535 536 @param ceed A Ceed object where the CeedElemRestriction will be created. 537 @param num_elem Number of elements described in the @a offsets array. 538 @param elem_size Size (number of unknowns) per element 539 @param blk_size Number of elements in a block 540 @param num_comp Number of field components per interpolation node 541 (1 for scalar fields) 542 @param comp_stride Stride between components for the same L-vector "node". 543 Data for node i, component j, element k can be found in 544 the L-vector at index 545 offsets[i + k*elem_size] + j*comp_stride. 546 @param l_size The size of the L-vector. This vector may be larger than 547 the elements and fields given by this restriction. 548 @param mem_type Memory type of the @a offsets array, see CeedMemType 549 @param copy_mode Copy mode for the @a offsets array, see CeedCopyMode 550 @param offsets Array of shape [@a num_elem, @a elem_size]. Row i holds the 551 ordered list of the offsets (into the input CeedVector) 552 for the unknowns corresponding to element i, where 553 0 <= i < @a num_elem. All offsets must be in the range 554 [0, @a l_size - 1]. The backend will permute and pad this 555 array to the desired ordering for the blocksize, which is 556 typically given by the backend. The default reordering is 557 to interlace elements. 558 @param rstr Address of the variable where the newly created 559 CeedElemRestriction will be stored 560 561 @return An error code: 0 - success, otherwise - failure 562 563 @ref Backend 564 **/ 565 int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt num_elem, 566 CeedInt elem_size, 567 CeedInt blk_size, CeedInt num_comp, 568 CeedInt comp_stride, CeedSize l_size, 569 CeedMemType mem_type, CeedCopyMode copy_mode, 570 const CeedInt *offsets, 571 CeedElemRestriction *rstr) { 572 int ierr; 573 CeedInt *blk_offsets; 574 CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size); 575 576 if (!ceed->ElemRestrictionCreateBlocked) { 577 Ceed delegate; 578 ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"); 579 CeedChk(ierr); 580 581 if (!delegate) 582 // LCOV_EXCL_START 583 return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support " 584 "ElemRestrictionCreateBlocked"); 585 // LCOV_EXCL_STOP 586 587 ierr = CeedElemRestrictionCreateBlocked(delegate, num_elem, elem_size, blk_size, 588 num_comp, comp_stride, l_size, mem_type, 589 copy_mode, offsets, rstr); 590 CeedChk(ierr); 591 return CEED_ERROR_SUCCESS; 592 } 593 594 ierr = CeedCalloc(1, rstr); CeedChk(ierr); 595 596 ierr = CeedCalloc(num_blk*blk_size*elem_size, &blk_offsets); CeedChk(ierr); 597 ierr = CeedPermutePadOffsets(offsets, blk_offsets, num_blk, num_elem, blk_size, 598 elem_size); CeedChk(ierr); 599 600 (*rstr)->ceed = ceed; 601 ierr = CeedReference(ceed); CeedChk(ierr); 602 (*rstr)->ref_count = 1; 603 (*rstr)->num_elem = num_elem; 604 (*rstr)->elem_size = elem_size; 605 (*rstr)->num_comp = num_comp; 606 (*rstr)->comp_stride = comp_stride; 607 (*rstr)->l_size = l_size; 608 (*rstr)->num_blk = num_blk; 609 (*rstr)->blk_size = blk_size; 610 (*rstr)->is_oriented = 0; 611 ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, 612 (const CeedInt *) blk_offsets, *rstr); CeedChk(ierr); 613 if (copy_mode == CEED_OWN_POINTER) { 614 ierr = CeedFree(&offsets); CeedChk(ierr); 615 } 616 return CEED_ERROR_SUCCESS; 617 } 618 619 /** 620 @brief Create a blocked strided CeedElemRestriction 621 622 @param ceed A Ceed object where the CeedElemRestriction will be created 623 @param num_elem Number of elements described by the restriction 624 @param elem_size Size (number of "nodes") per element 625 @param blk_size Number of elements in a block 626 @param num_comp Number of field components per interpolation node 627 (1 for scalar fields) 628 @param l_size The size of the L-vector. This vector may be larger than 629 the elements and fields given by this restriction. 630 @param strides Array for strides between [nodes, components, elements]. 631 Data for node i, component j, element k can be found in 632 the L-vector at index 633 i*strides[0] + j*strides[1] + k*strides[2]. 634 @a CEED_STRIDES_BACKEND may be used with vectors created 635 by a Ceed backend. 636 @param rstr Address of the variable where the newly created 637 CeedElemRestriction will be stored 638 639 @return An error code: 0 - success, otherwise - failure 640 641 @ref User 642 **/ 643 int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt num_elem, 644 CeedInt elem_size, CeedInt blk_size, CeedInt num_comp, CeedSize l_size, 645 const CeedInt strides[3], CeedElemRestriction *rstr) { 646 int ierr; 647 CeedInt num_blk = (num_elem / blk_size) + !!(num_elem % blk_size); 648 649 if (!ceed->ElemRestrictionCreateBlocked) { 650 Ceed delegate; 651 ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"); 652 CeedChk(ierr); 653 654 if (!delegate) 655 // LCOV_EXCL_START 656 return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support " 657 "ElemRestrictionCreateBlocked"); 658 // LCOV_EXCL_STOP 659 660 ierr = CeedElemRestrictionCreateBlockedStrided(delegate, num_elem, elem_size, 661 blk_size, num_comp, l_size, strides, rstr); CeedChk(ierr); 662 return CEED_ERROR_SUCCESS; 663 } 664 665 ierr = CeedCalloc(1, rstr); CeedChk(ierr); 666 667 (*rstr)->ceed = ceed; 668 ierr = CeedReference(ceed); CeedChk(ierr); 669 (*rstr)->ref_count = 1; 670 (*rstr)->num_elem = num_elem; 671 (*rstr)->elem_size = elem_size; 672 (*rstr)->num_comp = num_comp; 673 (*rstr)->l_size = l_size; 674 (*rstr)->num_blk = num_blk; 675 (*rstr)->blk_size = blk_size; 676 (*rstr)->is_oriented = 0; 677 ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr); 678 for (int i=0; i<3; i++) 679 (*rstr)->strides[i] = strides[i]; 680 ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, 681 NULL, *rstr); CeedChk(ierr); 682 return CEED_ERROR_SUCCESS; 683 } 684 685 /** 686 @brief Copy the pointer to a CeedElemRestriction. Both pointers should 687 be destroyed with `CeedElemRestrictionDestroy()`; 688 Note: If `*rstr_copy` is non-NULL, then it is assumed that 689 `*rstr_copy` is a pointer to a CeedElemRestriction. This 690 CeedElemRestriction will be destroyed if `*rstr_copy` is the 691 only reference to this CeedElemRestriction. 692 693 @param rstr CeedElemRestriction to copy reference to 694 @param[out] rstr_copy Variable to store copied reference 695 696 @return An error code: 0 - success, otherwise - failure 697 698 @ref User 699 **/ 700 int CeedElemRestrictionReferenceCopy(CeedElemRestriction rstr, 701 CeedElemRestriction *rstr_copy) { 702 int ierr; 703 704 ierr = CeedElemRestrictionReference(rstr); CeedChk(ierr); 705 ierr = CeedElemRestrictionDestroy(rstr_copy); CeedChk(ierr); 706 *rstr_copy = rstr; 707 return CEED_ERROR_SUCCESS; 708 } 709 710 /** 711 @brief Create CeedVectors associated with a CeedElemRestriction 712 713 @param rstr CeedElemRestriction 714 @param l_vec The address of the L-vector to be created, or NULL 715 @param e_vec The address of the E-vector to be created, or NULL 716 717 @return An error code: 0 - success, otherwise - failure 718 719 @ref User 720 **/ 721 int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *l_vec, 722 CeedVector *e_vec) { 723 int ierr; 724 CeedSize e_size, l_size; 725 l_size = rstr->l_size; 726 e_size = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp; 727 if (l_vec) { 728 ierr = CeedVectorCreate(rstr->ceed, l_size, l_vec); CeedChk(ierr); 729 } 730 if (e_vec) { 731 ierr = CeedVectorCreate(rstr->ceed, e_size, e_vec); CeedChk(ierr); 732 } 733 return CEED_ERROR_SUCCESS; 734 } 735 736 /** 737 @brief Restrict an L-vector to an E-vector or apply its transpose 738 739 @param rstr CeedElemRestriction 740 @param t_mode Apply restriction or transpose 741 @param u Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE) 742 @param ru Output vector (of shape [@a num_elem * @a elem_size] when 743 t_mode=@ref CEED_NOTRANSPOSE). Ordering of the e-vector is decided 744 by the backend. 745 @param request Request or @ref CEED_REQUEST_IMMEDIATE 746 747 @return An error code: 0 - success, otherwise - failure 748 749 @ref User 750 **/ 751 int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode t_mode, 752 CeedVector u, CeedVector ru, 753 CeedRequest *request) { 754 CeedInt m, n; 755 int ierr; 756 757 if (t_mode == CEED_NOTRANSPOSE) { 758 m = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp; 759 n = rstr->l_size; 760 } else { 761 m = rstr->l_size; 762 n = rstr->num_blk * rstr->blk_size * rstr->elem_size * rstr->num_comp; 763 } 764 if (n != u->length) 765 // LCOV_EXCL_START 766 return CeedError(rstr->ceed, CEED_ERROR_DIMENSION, 767 "Input vector size %d not compatible with " 768 "element restriction (%d, %d)", u->length, m, n); 769 // LCOV_EXCL_STOP 770 if (m != ru->length) 771 // LCOV_EXCL_START 772 return CeedError(rstr->ceed, CEED_ERROR_DIMENSION, 773 "Output vector size %d not compatible with " 774 "element restriction (%d, %d)", ru->length, m, n); 775 // LCOV_EXCL_STOP 776 ierr = rstr->Apply(rstr, t_mode, u, ru, request); CeedChk(ierr); 777 return CEED_ERROR_SUCCESS; 778 } 779 780 /** 781 @brief Restrict an L-vector to a block of an E-vector or apply its transpose 782 783 @param rstr CeedElemRestriction 784 @param block Block number to restrict to/from, i.e. block=0 will handle 785 elements [0 : blk_size] and block=3 will handle elements 786 [3*blk_size : 4*blk_size] 787 @param t_mode Apply restriction or transpose 788 @param u Input vector (of size @a l_size when t_mode=@ref CEED_NOTRANSPOSE) 789 @param ru Output vector (of shape [@a blk_size * @a elem_size] when 790 t_mode=@ref CEED_NOTRANSPOSE). Ordering of the e-vector is decided 791 by the backend. 792 @param request Request or @ref CEED_REQUEST_IMMEDIATE 793 794 @return An error code: 0 - success, otherwise - failure 795 796 @ref Backend 797 **/ 798 int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, 799 CeedTransposeMode t_mode, CeedVector u, 800 CeedVector ru, CeedRequest *request) { 801 CeedInt m, n; 802 int ierr; 803 804 if (t_mode == CEED_NOTRANSPOSE) { 805 m = rstr->blk_size * rstr->elem_size * rstr->num_comp; 806 n = rstr->l_size; 807 } else { 808 m = rstr->l_size; 809 n = rstr->blk_size * rstr->elem_size * rstr->num_comp; 810 } 811 if (n != u->length) 812 // LCOV_EXCL_START 813 return CeedError(rstr->ceed, CEED_ERROR_DIMENSION, 814 "Input vector size %d not compatible with " 815 "element restriction (%d, %d)", u->length, m, n); 816 // LCOV_EXCL_STOP 817 if (m != ru->length) 818 // LCOV_EXCL_START 819 return CeedError(rstr->ceed, CEED_ERROR_DIMENSION, 820 "Output vector size %d not compatible with " 821 "element restriction (%d, %d)", ru->length, m, n); 822 // LCOV_EXCL_STOP 823 if (rstr->blk_size*block > rstr->num_elem) 824 // LCOV_EXCL_START 825 return CeedError(rstr->ceed, CEED_ERROR_DIMENSION, 826 "Cannot retrieve block %d, element %d > " 827 "total elements %d", block, rstr->blk_size*block, 828 rstr->num_elem); 829 // LCOV_EXCL_STOP 830 ierr = rstr->ApplyBlock(rstr, block, t_mode, u, ru, request); 831 CeedChk(ierr); 832 return CEED_ERROR_SUCCESS; 833 } 834 835 /** 836 @brief Get the Ceed associated with a CeedElemRestriction 837 838 @param rstr CeedElemRestriction 839 @param[out] ceed Variable to store Ceed 840 841 @return An error code: 0 - success, otherwise - failure 842 843 @ref Advanced 844 **/ 845 int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) { 846 *ceed = rstr->ceed; 847 return CEED_ERROR_SUCCESS; 848 } 849 850 /** 851 @brief Get the L-vector component stride 852 853 @param rstr CeedElemRestriction 854 @param[out] comp_stride Variable to store component stride 855 856 @return An error code: 0 - success, otherwise - failure 857 858 @ref Advanced 859 **/ 860 int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, 861 CeedInt *comp_stride) { 862 *comp_stride = rstr->comp_stride; 863 return CEED_ERROR_SUCCESS; 864 } 865 866 /** 867 @brief Get the total number of elements in the range of a CeedElemRestriction 868 869 @param rstr CeedElemRestriction 870 @param[out] num_elem Variable to store number of elements 871 872 @return An error code: 0 - success, otherwise - failure 873 874 @ref Advanced 875 **/ 876 int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, 877 CeedInt *num_elem) { 878 *num_elem = rstr->num_elem; 879 return CEED_ERROR_SUCCESS; 880 } 881 882 /** 883 @brief Get the size of elements in the CeedElemRestriction 884 885 @param rstr CeedElemRestriction 886 @param[out] elem_size Variable to store size of elements 887 888 @return An error code: 0 - success, otherwise - failure 889 890 @ref Advanced 891 **/ 892 int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, 893 CeedInt *elem_size) { 894 *elem_size = rstr->elem_size; 895 return CEED_ERROR_SUCCESS; 896 } 897 898 /** 899 @brief Get the size of the l-vector for a CeedElemRestriction 900 901 @param rstr CeedElemRestriction 902 @param[out] l_size Variable to store number of nodes 903 904 @return An error code: 0 - success, otherwise - failure 905 906 @ref Advanced 907 **/ 908 int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, 909 CeedSize *l_size) { 910 *l_size = rstr->l_size; 911 return CEED_ERROR_SUCCESS; 912 } 913 914 /** 915 @brief Get the number of components in the elements of a 916 CeedElemRestriction 917 918 @param rstr CeedElemRestriction 919 @param[out] num_comp Variable to store number of components 920 921 @return An error code: 0 - success, otherwise - failure 922 923 @ref Advanced 924 **/ 925 int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, 926 CeedInt *num_comp) { 927 *num_comp = rstr->num_comp; 928 return CEED_ERROR_SUCCESS; 929 } 930 931 /** 932 @brief Get the number of blocks in a CeedElemRestriction 933 934 @param rstr CeedElemRestriction 935 @param[out] num_block Variable to store number of blocks 936 937 @return An error code: 0 - success, otherwise - failure 938 939 @ref Advanced 940 **/ 941 int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, 942 CeedInt *num_block) { 943 *num_block = rstr->num_blk; 944 return CEED_ERROR_SUCCESS; 945 } 946 947 /** 948 @brief Get the size of blocks in the CeedElemRestriction 949 950 @param rstr CeedElemRestriction 951 @param[out] blk_size Variable to store size of blocks 952 953 @return An error code: 0 - success, otherwise - failure 954 955 @ref Advanced 956 **/ 957 int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, 958 CeedInt *blk_size) { 959 *blk_size = rstr->blk_size; 960 return CEED_ERROR_SUCCESS; 961 } 962 963 /** 964 @brief Get the multiplicity of nodes in a CeedElemRestriction 965 966 @param rstr CeedElemRestriction 967 @param[out] mult Vector to store multiplicity (of size l_size) 968 969 @return An error code: 0 - success, otherwise - failure 970 971 @ref User 972 **/ 973 int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, 974 CeedVector mult) { 975 int ierr; 976 CeedVector e_vec; 977 978 // Create e_vec to hold intermediate computation in E^T (E 1) 979 ierr = CeedElemRestrictionCreateVector(rstr, NULL, &e_vec); CeedChk(ierr); 980 981 // Compute e_vec = E * 1 982 ierr = CeedVectorSetValue(mult, 1.0); CeedChk(ierr); 983 ierr = CeedElemRestrictionApply(rstr, CEED_NOTRANSPOSE, mult, e_vec, 984 CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 985 // Compute multiplicity, mult = E^T * e_vec = E^T (E 1) 986 ierr = CeedVectorSetValue(mult, 0.0); CeedChk(ierr); 987 ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, e_vec, mult, 988 CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 989 // Cleanup 990 ierr = CeedVectorDestroy(&e_vec); CeedChk(ierr); 991 return CEED_ERROR_SUCCESS; 992 } 993 994 /** 995 @brief View a CeedElemRestriction 996 997 @param[in] rstr CeedElemRestriction to view 998 @param[in] stream Stream to write; typically stdout/stderr or a file 999 1000 @return Error code: 0 - success, otherwise - failure 1001 1002 @ref User 1003 **/ 1004 int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) { 1005 char stridesstr[500]; 1006 if (rstr->strides) 1007 sprintf(stridesstr, "[%d, %d, %d]", rstr->strides[0], rstr->strides[1], 1008 rstr->strides[2]); 1009 else 1010 sprintf(stridesstr, "%d", rstr->comp_stride); 1011 1012 fprintf(stream, "%sCeedElemRestriction from (%td, %d) to %d elements with %d " 1013 "nodes each and %s %s\n", rstr->blk_size > 1 ? "Blocked " : "", 1014 rstr->l_size, rstr->num_comp, rstr->num_elem, rstr->elem_size, 1015 rstr->strides ? "strides" : "component stride", stridesstr); 1016 return CEED_ERROR_SUCCESS; 1017 } 1018 1019 /** 1020 @brief Destroy a CeedElemRestriction 1021 1022 @param rstr CeedElemRestriction to destroy 1023 1024 @return An error code: 0 - success, otherwise - failure 1025 1026 @ref User 1027 **/ 1028 int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) { 1029 int ierr; 1030 1031 if (!*rstr || --(*rstr)->ref_count > 0) return CEED_ERROR_SUCCESS; 1032 if ((*rstr)->num_readers) 1033 // LCOV_EXCL_START 1034 return CeedError((*rstr)->ceed, CEED_ERROR_ACCESS, 1035 "Cannot destroy CeedElemRestriction, " 1036 "a process has read access to the offset data"); 1037 // LCOV_EXCL_STOP 1038 if ((*rstr)->Destroy) { 1039 ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr); 1040 } 1041 ierr = CeedFree(&(*rstr)->strides); CeedChk(ierr); 1042 ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr); 1043 ierr = CeedFree(rstr); CeedChk(ierr); 1044 return CEED_ERROR_SUCCESS; 1045 } 1046 1047 /// @} 1048