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] isstrided 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 CeedElemRestrictionIsStrided(CeedElemRestriction rstr, bool *isstrided) { 160 *isstrided = rstr->strides ? 1 : 0; 161 return 0; 162 } 163 164 /** 165 @brief Get the backend stride status of a CeedElemRestriction 166 167 @param rstr CeedElemRestriction 168 @param[out] status Variable to store stride status 169 170 @return An error code: 0 - success, otherwise - failure 171 172 @ref Backend 173 **/ 174 int CeedElemRestrictionHasBackendStrides(CeedElemRestriction rstr, 175 bool *hasbackendstrides) { 176 if (!rstr->strides) 177 // LCOV_EXCL_START 178 return CeedError(rstr->ceed, 1, "ElemRestriction has no stride data"); 179 // LCOV_EXCL_STOP 180 181 *hasbackendstrides = ((rstr->strides[0] == CEED_STRIDES_BACKEND[0]) && 182 (rstr->strides[1] == CEED_STRIDES_BACKEND[1]) && 183 (rstr->strides[2] == CEED_STRIDES_BACKEND[2])); 184 return 0; 185 } 186 187 /** 188 189 @brief Get the E-vector layout of a CeedElemRestriction 190 191 @param rstr CeedElemRestriction 192 @param[out] layout Variable to store layout array, 193 stored as [nodes, components, elements]. 194 The data for node i, component j, element k in the 195 E-vector is given by 196 i*layout[0] + j*layout[1] + k*layout[2] 197 198 @return An error code: 0 - success, otherwise - failure 199 200 @ref Backend 201 **/ 202 int CeedElemRestrictionGetELayout(CeedElemRestriction rstr, 203 CeedInt (*layout)[3]) { 204 if (!rstr->layout[0]) 205 // LCOV_EXCL_START 206 return CeedError(rstr->ceed, 1, "ElemRestriction has no layout data"); 207 // LCOV_EXCL_STOP 208 209 for (int i = 0; i<3; i++) 210 (*layout)[i] = rstr->layout[i]; 211 return 0; 212 } 213 214 /** 215 216 @brief Set the E-vector layout of a CeedElemRestriction 217 218 @param rstr CeedElemRestriction 219 @param layout Variable to containing layout array, 220 stored as [nodes, components, elements]. 221 The data for node i, component j, element k in the 222 E-vector is given by 223 i*layout[0] + j*layout[1] + k*layout[2] 224 225 @return An error code: 0 - success, otherwise - failure 226 227 @ref Backend 228 **/ 229 int CeedElemRestrictionSetELayout(CeedElemRestriction rstr, 230 CeedInt layout[3]) { 231 for (int i = 0; i<3; i++) 232 rstr->layout[i] = layout[i]; 233 return 0; 234 } 235 236 /** 237 @brief Get the backend data of a CeedElemRestriction 238 239 @param rstr CeedElemRestriction 240 @param[out] data Variable to store data 241 242 @return An error code: 0 - success, otherwise - failure 243 244 @ref Backend 245 **/ 246 int CeedElemRestrictionGetData(CeedElemRestriction rstr, void **data) { 247 *data = rstr->data; 248 return 0; 249 } 250 251 /** 252 @brief Set the backend data of a CeedElemRestriction 253 254 @param[out] rstr CeedElemRestriction 255 @param data Data to set 256 257 @return An error code: 0 - success, otherwise - failure 258 259 @ref Backend 260 **/ 261 int CeedElemRestrictionSetData(CeedElemRestriction rstr, void **data) { 262 rstr->data = *data; 263 return 0; 264 } 265 266 /// @} 267 268 /// @cond DOXYGEN_SKIP 269 static struct CeedElemRestriction_private ceed_elemrestriction_none; 270 /// @endcond 271 272 /// ---------------------------------------------------------------------------- 273 /// CeedElemRestriction Public API 274 /// ---------------------------------------------------------------------------- 275 /// @addtogroup CeedElemRestrictionUser 276 /// @{ 277 278 /// Indicate that the stride is determined by the backend 279 const CeedInt CEED_STRIDES_BACKEND[3] = {}; 280 281 /// Indicate that no CeedElemRestriction is provided by the user 282 const CeedElemRestriction CEED_ELEMRESTRICTION_NONE = 283 &ceed_elemrestriction_none; 284 285 /** 286 @brief Create a CeedElemRestriction 287 288 @param ceed A Ceed object where the CeedElemRestriction will be created 289 @param nelem Number of elements described in the @a offsets array 290 @param elemsize Size (number of "nodes") per element 291 @param ncomp Number of field components per interpolation node 292 (1 for scalar fields) 293 @param compstride Stride between components for the same L-vector "node". 294 Data for node i, component j, element k can be found in 295 the L-vector at index 296 offsets[i + k*elemsize] + j*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 Data for node i, component j, element k can be found in 364 the L-vector at index 365 i*strides[0] + j*strides[1] + k*strides[2]. 366 @a CEED_STRIDES_BACKEND may be used with vectors created 367 by a Ceed backend. 368 @param rstr Address of the variable where the newly created 369 CeedElemRestriction will be stored 370 371 @return An error code: 0 - success, otherwise - failure 372 373 @ref User 374 **/ 375 int CeedElemRestrictionCreateStrided(Ceed ceed, CeedInt nelem, CeedInt elemsize, 376 CeedInt ncomp, CeedInt lsize, 377 const CeedInt strides[3], 378 CeedElemRestriction *rstr) { 379 int ierr; 380 381 if (!ceed->ElemRestrictionCreate) { 382 Ceed delegate; 383 ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"); 384 CeedChk(ierr); 385 386 if (!delegate) 387 // LCOV_EXCL_START 388 return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate"); 389 // LCOV_EXCL_STOP 390 391 ierr = CeedElemRestrictionCreateStrided(delegate, nelem, elemsize, ncomp, 392 lsize, strides, rstr); 393 CeedChk(ierr); 394 return 0; 395 } 396 397 ierr = CeedCalloc(1, rstr); CeedChk(ierr); 398 (*rstr)->ceed = ceed; 399 ceed->refcount++; 400 (*rstr)->refcount = 1; 401 (*rstr)->nelem = nelem; 402 (*rstr)->elemsize = elemsize; 403 (*rstr)->ncomp = ncomp; 404 (*rstr)->lsize = lsize; 405 (*rstr)->nblk = nelem; 406 (*rstr)->blksize = 1; 407 ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr); 408 for (int i = 0; i<3; i++) 409 (*rstr)->strides[i] = strides[i]; 410 ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, 411 *rstr); 412 CeedChk(ierr); 413 return 0; 414 } 415 416 /** 417 @brief Create a blocked CeedElemRestriction, typically only called by backends 418 419 @param ceed A Ceed object where the CeedElemRestriction will be created. 420 @param nelem Number of elements described in the @a offsets array. 421 @param elemsize Size (number of unknowns) per element 422 @param blksize Number of elements in a block 423 @param ncomp Number of field components per interpolation node 424 (1 for scalar fields) 425 @param compstride Stride between components for the same L-vector "node". 426 Data for node i, component j, element k can be found in 427 the L-vector at index 428 offsets[i + k*elemsize] + j*compstride. 429 @param lsize The size of the L-vector. This vector may be larger than 430 the elements and fields given by this restriction. 431 @param mtype Memory type of the @a offsets array, see CeedMemType 432 @param cmode Copy mode for the @a offsets array, see CeedCopyMode 433 @param offsets Array of shape [@a nelem, @a elemsize]. Row i holds the 434 ordered list of the offsets (into the input CeedVector) 435 for the unknowns corresponding to element i, where 436 0 <= i < @a nelem. All offsets must be in the range 437 [0, @a lsize - 1]. The backend will permute and pad this 438 array to the desired ordering for the blocksize, which is 439 typically given by the backend. The default reordering is 440 to interlace elements. 441 @param rstr Address of the variable where the newly created 442 CeedElemRestriction will be stored 443 444 @return An error code: 0 - success, otherwise - failure 445 446 @ref Backend 447 **/ 448 int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt nelem, CeedInt elemsize, 449 CeedInt blksize, CeedInt ncomp, 450 CeedInt compstride, CeedInt lsize, 451 CeedMemType mtype, CeedCopyMode cmode, 452 const CeedInt *offsets, 453 CeedElemRestriction *rstr) { 454 int ierr; 455 CeedInt *blkoffsets; 456 CeedInt nblk = (nelem / blksize) + !!(nelem % blksize); 457 458 if (!ceed->ElemRestrictionCreateBlocked) { 459 Ceed delegate; 460 ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"); 461 CeedChk(ierr); 462 463 if (!delegate) 464 // LCOV_EXCL_START 465 return CeedError(ceed, 1, "Backend does not support " 466 "ElemRestrictionCreateBlocked"); 467 // LCOV_EXCL_STOP 468 469 ierr = CeedElemRestrictionCreateBlocked(delegate, nelem, elemsize, blksize, 470 ncomp, compstride, lsize, mtype, 471 cmode, offsets, rstr); 472 CeedChk(ierr); 473 return 0; 474 } 475 476 ierr = CeedCalloc(1, rstr); CeedChk(ierr); 477 478 ierr = CeedCalloc(nblk*blksize*elemsize, &blkoffsets); CeedChk(ierr); 479 ierr = CeedPermutePadOffsets(offsets, blkoffsets, nblk, nelem, blksize, 480 elemsize); 481 CeedChk(ierr); 482 483 (*rstr)->ceed = ceed; 484 ceed->refcount++; 485 (*rstr)->refcount = 1; 486 (*rstr)->nelem = nelem; 487 (*rstr)->elemsize = elemsize; 488 (*rstr)->ncomp = ncomp; 489 (*rstr)->compstride = compstride; 490 (*rstr)->lsize = lsize; 491 (*rstr)->nblk = nblk; 492 (*rstr)->blksize = blksize; 493 ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, 494 (const CeedInt *) blkoffsets, *rstr); CeedChk(ierr); 495 496 if (cmode == CEED_OWN_POINTER) { 497 ierr = CeedFree(&offsets); CeedChk(ierr); 498 } 499 500 return 0; 501 } 502 503 /** 504 @brief Create a blocked strided CeedElemRestriction 505 506 @param ceed A Ceed object where the CeedElemRestriction will be created 507 @param nelem Number of elements described by the restriction 508 @param elemsize Size (number of "nodes") per element 509 @param blksize Number of elements in a block 510 @param ncomp Number of field components per interpolation node 511 (1 for scalar fields) 512 @param lsize The size of the L-vector. This vector may be larger than 513 the elements and fields given by this restriction. 514 @param strides Array for strides between [nodes, components, elements]. 515 Data for node i, component j, element k can be found in 516 the L-vector at index 517 i*strides[0] + j*strides[1] + k*strides[2]. 518 @a CEED_STRIDES_BACKEND may be used with vectors created 519 by a Ceed backend. 520 @param rstr Address of the variable where the newly created 521 CeedElemRestriction will be stored 522 523 @return An error code: 0 - success, otherwise - failure 524 525 @ref User 526 **/ 527 int CeedElemRestrictionCreateBlockedStrided(Ceed ceed, CeedInt nelem, 528 CeedInt elemsize, CeedInt blksize, CeedInt ncomp, CeedInt lsize, 529 const CeedInt strides[3], CeedElemRestriction *rstr) { 530 int ierr; 531 CeedInt nblk = (nelem / blksize) + !!(nelem % blksize); 532 533 if (!ceed->ElemRestrictionCreateBlocked) { 534 Ceed delegate; 535 ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"); 536 CeedChk(ierr); 537 538 if (!delegate) 539 // LCOV_EXCL_START 540 return CeedError(ceed, 1, "Backend does not support " 541 "ElemRestrictionCreateBlocked"); 542 // LCOV_EXCL_STOP 543 544 ierr = CeedElemRestrictionCreateBlockedStrided(delegate, nelem, elemsize, 545 blksize, ncomp, lsize, strides, rstr); 546 CeedChk(ierr); 547 return 0; 548 } 549 550 ierr = CeedCalloc(1, rstr); CeedChk(ierr); 551 552 (*rstr)->ceed = ceed; 553 ceed->refcount++; 554 (*rstr)->refcount = 1; 555 (*rstr)->nelem = nelem; 556 (*rstr)->elemsize = elemsize; 557 (*rstr)->ncomp = ncomp; 558 (*rstr)->lsize = lsize; 559 (*rstr)->nblk = nblk; 560 (*rstr)->blksize = blksize; 561 ierr = CeedMalloc(3, &(*rstr)->strides); CeedChk(ierr); 562 for (int i = 0; i<3; i++) 563 (*rstr)->strides[i] = strides[i]; 564 ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, 565 NULL, *rstr); CeedChk(ierr); 566 567 return 0; 568 } 569 570 /** 571 @brief Create CeedVectors associated with a CeedElemRestriction 572 573 @param rstr CeedElemRestriction 574 @param lvec The address of the L-vector to be created, or NULL 575 @param evec The address of the E-vector to be created, or NULL 576 577 @return An error code: 0 - success, otherwise - failure 578 579 @ref User 580 **/ 581 int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *lvec, 582 CeedVector *evec) { 583 int ierr; 584 CeedInt n, m; 585 m = rstr->lsize; 586 n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp; 587 if (lvec) { 588 ierr = CeedVectorCreate(rstr->ceed, m, lvec); CeedChk(ierr); 589 } 590 if (evec) { 591 ierr = CeedVectorCreate(rstr->ceed, n, evec); CeedChk(ierr); 592 } 593 return 0; 594 } 595 596 /** 597 @brief Restrict an L-vector to an E-vector or apply its transpose 598 599 @param rstr CeedElemRestriction 600 @param tmode Apply restriction or transpose 601 @param u Input vector (of size @a lsize when tmode=@ref CEED_NOTRANSPOSE) 602 @param ru Output vector (of shape [@a nelem * @a elemsize] when 603 tmode=@ref CEED_NOTRANSPOSE). Ordering of the e-vector is decided 604 by the backend. 605 @param request Request or @ref CEED_REQUEST_IMMEDIATE 606 607 @return An error code: 0 - success, otherwise - failure 608 609 @ref User 610 **/ 611 int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode tmode, 612 CeedVector u, CeedVector ru, 613 CeedRequest *request) { 614 CeedInt m,n; 615 int ierr; 616 617 if (tmode == CEED_NOTRANSPOSE) { 618 m = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp; 619 n = rstr->lsize; 620 } else { 621 m = rstr->lsize; 622 n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp; 623 } 624 if (n != u->length) 625 // LCOV_EXCL_START 626 return CeedError(rstr->ceed, 2, "Input vector size %d not compatible with " 627 "element restriction (%d, %d)", u->length, m, n); 628 // LCOV_EXCL_STOP 629 if (m != ru->length) 630 // LCOV_EXCL_START 631 return CeedError(rstr->ceed, 2, "Output vector size %d not compatible with " 632 "element restriction (%d, %d)", ru->length, m, n); 633 // LCOV_EXCL_STOP 634 ierr = rstr->Apply(rstr, tmode, u, ru, request); CeedChk(ierr); 635 636 return 0; 637 } 638 639 /** 640 @brief Restrict an L-vector to a block of an E-vector or apply its transpose 641 642 @param rstr CeedElemRestriction 643 @param block Block number to restrict to/from, i.e. block=0 will handle 644 elements [0 : blksize] and block=3 will handle elements 645 [3*blksize : 4*blksize] 646 @param tmode Apply restriction or transpose 647 @param u Input vector (of size @a lsize when tmode=@ref CEED_NOTRANSPOSE) 648 @param ru Output vector (of shape [@a blksize * @a elemsize] when 649 tmode=@ref CEED_NOTRANSPOSE). Ordering of the e-vector is decided 650 by the backend. 651 @param request Request or @ref CEED_REQUEST_IMMEDIATE 652 653 @return An error code: 0 - success, otherwise - failure 654 655 @ref Backend 656 **/ 657 int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, 658 CeedTransposeMode tmode, CeedVector u, 659 CeedVector ru, CeedRequest *request) { 660 CeedInt m,n; 661 int ierr; 662 663 if (tmode == CEED_NOTRANSPOSE) { 664 m = rstr->blksize * rstr->elemsize * rstr->ncomp; 665 n = rstr->lsize; 666 } else { 667 m = rstr->lsize; 668 n = rstr->blksize * rstr->elemsize * rstr->ncomp; 669 } 670 if (n != u->length) 671 // LCOV_EXCL_START 672 return CeedError(rstr->ceed, 2, "Input vector size %d not compatible with " 673 "element restriction (%d, %d)", u->length, m, n); 674 // LCOV_EXCL_STOP 675 if (m != ru->length) 676 // LCOV_EXCL_START 677 return CeedError(rstr->ceed, 2, "Output vector size %d not compatible with " 678 "element restriction (%d, %d)", ru->length, m, n); 679 // LCOV_EXCL_STOP 680 if (rstr->blksize*block > rstr->nelem) 681 // LCOV_EXCL_START 682 return CeedError(rstr->ceed, 2, "Cannot retrieve block %d, element %d > " 683 "total elements %d", block, rstr->blksize*block, 684 rstr->nelem); 685 // LCOV_EXCL_STOP 686 ierr = rstr->ApplyBlock(rstr, block, tmode, u, ru, request); 687 CeedChk(ierr); 688 689 return 0; 690 } 691 692 /** 693 @brief Get the L-vector component stride 694 695 @param rstr CeedElemRestriction 696 @param[out] compstride Variable to store component stride 697 698 @return An error code: 0 - success, otherwise - failure 699 700 @ref Backend 701 **/ 702 int CeedElemRestrictionGetCompStride(CeedElemRestriction rstr, 703 CeedInt *compstride) { 704 *compstride = rstr->compstride; 705 return 0; 706 } 707 708 /** 709 @brief Get the total number of elements in the range of a CeedElemRestriction 710 711 @param rstr CeedElemRestriction 712 @param[out] numelem Variable to store number of elements 713 714 @return An error code: 0 - success, otherwise - failure 715 716 @ref Backend 717 **/ 718 int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, 719 CeedInt *numelem) { 720 *numelem = rstr->nelem; 721 return 0; 722 } 723 724 /** 725 @brief Get the size of elements in the CeedElemRestriction 726 727 @param rstr CeedElemRestriction 728 @param[out] elemsize Variable to store size of elements 729 730 @return An error code: 0 - success, otherwise - failure 731 732 @ref Backend 733 **/ 734 int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, 735 CeedInt *elemsize) { 736 *elemsize = rstr->elemsize; 737 return 0; 738 } 739 740 /** 741 @brief Get the size of the l-vector for a CeedElemRestriction 742 743 @param rstr CeedElemRestriction 744 @param[out] numnodes Variable to store number of nodes 745 746 @return An error code: 0 - success, otherwise - failure 747 748 @ref Backend 749 **/ 750 int CeedElemRestrictionGetLVectorSize(CeedElemRestriction rstr, 751 CeedInt *lsize) { 752 *lsize = rstr->lsize; 753 return 0; 754 } 755 756 /** 757 @brief Get the number of components in the elements of a 758 CeedElemRestriction 759 760 @param rstr CeedElemRestriction 761 @param[out] numcomp Variable to store number of components 762 763 @return An error code: 0 - success, otherwise - failure 764 765 @ref Backend 766 **/ 767 int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, 768 CeedInt *numcomp) { 769 *numcomp = rstr->ncomp; 770 return 0; 771 } 772 773 /** 774 @brief Get the number of blocks in a CeedElemRestriction 775 776 @param rstr CeedElemRestriction 777 @param[out] numblock Variable to store number of blocks 778 779 @return An error code: 0 - success, otherwise - failure 780 781 @ref Backend 782 **/ 783 int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, 784 CeedInt *numblock) { 785 *numblock = rstr->nblk; 786 return 0; 787 } 788 789 /** 790 @brief Get the size of blocks in the CeedElemRestriction 791 792 @param rstr CeedElemRestriction 793 @param[out] blksize Variable to store size of blocks 794 795 @return An error code: 0 - success, otherwise - failure 796 797 @ref Backend 798 **/ 799 int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, 800 CeedInt *blksize) { 801 *blksize = rstr->blksize; 802 return 0; 803 } 804 805 /** 806 @brief Get the multiplicity of nodes in a CeedElemRestriction 807 808 @param rstr CeedElemRestriction 809 @param[out] mult Vector to store multiplicity (of size lsize) 810 811 @return An error code: 0 - success, otherwise - failure 812 813 @ref User 814 **/ 815 int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, 816 CeedVector mult) { 817 int ierr; 818 CeedVector evec; 819 820 // Create and set evec 821 ierr = CeedElemRestrictionCreateVector(rstr, NULL, &evec); CeedChk(ierr); 822 ierr = CeedVectorSetValue(evec, 1.0); CeedChk(ierr); 823 ierr = CeedVectorSetValue(mult, 0.0); CeedChk(ierr); 824 825 // Apply to get multiplicity 826 ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, evec, mult, 827 CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 828 829 // Cleanup 830 ierr = CeedVectorDestroy(&evec); CeedChk(ierr); 831 832 return 0; 833 } 834 835 /** 836 @brief View a CeedElemRestriction 837 838 @param[in] rstr CeedElemRestriction to view 839 @param[in] stream Stream to write; typically stdout/stderr or a file 840 841 @return Error code: 0 - success, otherwise - failure 842 843 @ref User 844 **/ 845 int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) { 846 char stridesstr[500]; 847 if (rstr->strides) 848 sprintf(stridesstr, "[%d, %d, %d]", rstr->strides[0], rstr->strides[1], 849 rstr->strides[2]); 850 else 851 sprintf(stridesstr, "%d", rstr->compstride); 852 853 fprintf(stream, "%sCeedElemRestriction from (%d, %d) to %d elements with %d " 854 "nodes each and %s %s\n", rstr->blksize > 1 ? "Blocked " : "", 855 rstr->lsize, rstr->ncomp, rstr->nelem, rstr->elemsize, 856 rstr->strides ? "strides" : "component stride", stridesstr); 857 return 0; 858 } 859 860 /** 861 @brief Destroy a CeedElemRestriction 862 863 @param rstr CeedElemRestriction to destroy 864 865 @return An error code: 0 - success, otherwise - failure 866 867 @ref User 868 **/ 869 int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) { 870 int ierr; 871 872 if (!*rstr || --(*rstr)->refcount > 0) 873 return 0; 874 if ((*rstr)->numreaders) 875 return CeedError((*rstr)->ceed, 1, "Cannot destroy CeedElemRestriction, " 876 "a process has read access to the offset data"); 877 if ((*rstr)->Destroy) { 878 ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr); 879 } 880 ierr = CeedFree(&(*rstr)->strides); CeedChk(ierr); 881 ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr); 882 ierr = CeedFree(rstr); CeedChk(ierr); 883 return 0; 884 } 885 886 /// @} 887