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