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