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