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