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 public CeedElemRestriction interfaces 22 /// 23 /// @addtogroup CeedElemRestriction 24 /// @{ 25 26 /** 27 @brief Create a CeedElemRestriction 28 29 @param ceed A Ceed object where the CeedElemRestriction will be created 30 @param nelem Number of elements described in the @a indices array 31 @param elemsize Size (number of "nodes") per element 32 @param nnodes The number of nodes in the L-vector. The input CeedVector 33 to which the restriction will be applied is of size 34 @a nnodes * @a ncomp. This size may include data 35 used by other CeedElemRestriction objects describing 36 different types of elements. 37 @param ncomp Number of field components per interpolation node 38 @param mtype Memory type of the @a indices array, see CeedMemType 39 @param cmode Copy mode for the @a indices array, see CeedCopyMode 40 @param indices Array of shape [@a nelem, @a elemsize]. Row i holds the 41 ordered list of the indices (into the input CeedVector) 42 for the unknowns corresponding to element i, where 43 0 <= i < @a nelements. All indices must be in the range 44 [0, @a nnodes]. 45 @param[out] rstr Address of the variable where the newly created 46 CeedElemRestriction will be stored 47 48 @return An error code: 0 - success, otherwise - failure 49 50 @ref Basic 51 **/ 52 int CeedElemRestrictionCreate(Ceed ceed, CeedInt nelem, CeedInt elemsize, 53 CeedInt nnodes, CeedInt ncomp, CeedMemType mtype, 54 CeedCopyMode cmode, const CeedInt *indices, 55 CeedElemRestriction *rstr) { 56 int ierr; 57 58 if (!ceed->ElemRestrictionCreate) { 59 Ceed delegate; 60 ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"); 61 CeedChk(ierr); 62 63 if (!delegate) 64 return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate"); 65 66 ierr = CeedElemRestrictionCreate(delegate, nelem, elemsize, 67 nnodes, ncomp, mtype, cmode, 68 indices, rstr); CeedChk(ierr); 69 return 0; 70 } 71 72 ierr = CeedCalloc(1, rstr); CeedChk(ierr); 73 (*rstr)->ceed = ceed; 74 ceed->refcount++; 75 (*rstr)->refcount = 1; 76 (*rstr)->nelem = nelem; 77 (*rstr)->elemsize = elemsize; 78 (*rstr)->nnodes = nnodes; 79 (*rstr)->ncomp = ncomp; 80 (*rstr)->nblk = nelem; 81 (*rstr)->blksize = 1; 82 ierr = ceed->ElemRestrictionCreate(mtype, cmode, indices, *rstr); CeedChk(ierr); 83 return 0; 84 } 85 86 /** 87 @brief Create an identity CeedElemRestriction 88 89 @param ceed A Ceed object where the CeedElemRestriction will be created 90 @param nelem Number of elements described in the @a indices array 91 @param elemsize Size (number of "nodes") per element 92 @param nnodes The number of nodes in the L-vector. The input CeedVector 93 to which the restriction will be applied is of size 94 @a nnodes * @a ncomp. This size may include data 95 used by other CeedElemRestriction objects describing 96 different types of elements. 97 @param ncomp Number of field components per interpolation node 98 @param rstr Address of the variable where the newly created 99 CeedElemRestriction will be stored 100 101 @return An error code: 0 - success, otherwise - failure 102 103 @ref Basic 104 **/ 105 int CeedElemRestrictionCreateIdentity(Ceed ceed, CeedInt nelem, 106 CeedInt elemsize, CeedInt nnodes, 107 CeedInt ncomp, 108 CeedElemRestriction *rstr) { 109 int ierr; 110 111 if (!ceed->ElemRestrictionCreate) { 112 Ceed delegate; 113 ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"); 114 CeedChk(ierr); 115 116 if (!delegate) 117 return CeedError(ceed, 1, 118 "Backend does not support ElemRestrictionCreate"); 119 120 ierr = CeedElemRestrictionCreateIdentity(delegate, nelem, elemsize, 121 nnodes, ncomp, rstr); CeedChk(ierr); 122 return 0; 123 } 124 125 ierr = CeedCalloc(1, rstr); CeedChk(ierr); 126 (*rstr)->ceed = ceed; 127 ceed->refcount++; 128 (*rstr)->refcount = 1; 129 (*rstr)->nelem = nelem; 130 (*rstr)->elemsize = elemsize; 131 (*rstr)->nnodes = nnodes; 132 (*rstr)->ncomp = ncomp; 133 (*rstr)->nblk = nelem; 134 (*rstr)->blksize = 1; 135 ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, 136 *rstr); 137 CeedChk(ierr); 138 return 0; 139 } 140 141 /** 142 @brief Permute and pad indices for a blocked restriction 143 144 @param indices Array of shape [@a nelem, @a elemsize]. Row i holds the 145 ordered list of the indices (into the input CeedVector) 146 for the unknowns corresponding to element i, where 147 0 <= i < @a nelements. All indices must be in the range 148 [0, @a nnodes). 149 @param blkindices Array of permuted and padded indices of 150 shape [@a nblk, @a elemsize, @a blksize]. 151 @param nblk Number of blocks 152 @param nelem Number of elements 153 @param blksize Number of elements in a block 154 @param elemsize Size of each element 155 156 @return An error code: 0 - success, otherwise - failure 157 158 @ref Utility 159 **/ 160 int CeedPermutePadIndices(const CeedInt *indices, CeedInt *blkindices, 161 CeedInt nblk, CeedInt nelem, 162 CeedInt blksize, CeedInt elemsize) { 163 for (CeedInt e = 0; e < nblk*blksize; e+=blksize) 164 for (int j = 0; j < blksize; j++) 165 for (int k = 0; k < elemsize; k++) 166 blkindices[e*elemsize + k*blksize + j] 167 = indices[CeedIntMin(e+j,nelem-1)*elemsize + k]; 168 return 0; 169 } 170 171 /** 172 @brief Create a blocked CeedElemRestriction, typically only called by backends 173 174 @param ceed A Ceed object where the CeedElemRestriction will be created. 175 @param nelem Number of elements described in the @a indices array. 176 @param elemsize Size (number of unknowns) per element 177 @param blksize Number of elements in a block 178 @param nnodes The number of nodes in the L-vector. The input CeedVector 179 to which the restriction will be applied is of size 180 @a nnodes * @a ncomp. This size may include data 181 used by other CeedElemRestriction objects describing 182 different types of elements. 183 @param ncomp Number of components stored at each node 184 @param mtype Memory type of the @a indices array, see CeedMemType 185 @param cmode Copy mode for the @a indices array, see CeedCopyMode 186 @param indices Array of shape [@a nelem, @a elemsize]. Row i holds the 187 ordered list of the indices (into the input CeedVector) 188 for the unknowns corresponding to element i, where 189 0 <= i < @a nelements. All indices must be in the range 190 [0, @a nnodes). The backend will permute and pad this 191 array to the desired ordering for the blocksize, which is 192 typically given by the backend. The default reordering is 193 to interlace elements. 194 @param rstr Address of the variable where the newly created 195 CeedElemRestriction will be stored 196 197 @return An error code: 0 - success, otherwise - failure 198 199 @ref Advanced 200 **/ 201 int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt nelem, CeedInt elemsize, 202 CeedInt blksize, CeedInt nnodes, 203 CeedInt ncomp, CeedMemType mtype, 204 CeedCopyMode cmode, const CeedInt *indices, 205 CeedElemRestriction *rstr) { 206 int ierr; 207 CeedInt *blkindices; 208 CeedInt nblk = (nelem / blksize) + !!(nelem % blksize); 209 210 if (!ceed->ElemRestrictionCreateBlocked) { 211 Ceed delegate; 212 ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction"); 213 CeedChk(ierr); 214 215 if (!delegate) 216 return CeedError(ceed, 1, 217 "Backend does not support ElemRestrictionCreateBlocked"); 218 219 ierr = CeedElemRestrictionCreateBlocked(delegate, nelem, elemsize, 220 blksize, nnodes, ncomp, mtype, cmode, 221 indices, rstr); CeedChk(ierr); 222 return 0; 223 } 224 225 ierr = CeedCalloc(1, rstr); CeedChk(ierr); 226 227 if (indices) { 228 ierr = CeedCalloc(nblk*blksize*elemsize, &blkindices); CeedChk(ierr); 229 ierr = CeedPermutePadIndices(indices, blkindices, nblk, nelem, blksize, 230 elemsize); 231 CeedChk(ierr); 232 } else { 233 blkindices = NULL; 234 } 235 236 (*rstr)->ceed = ceed; 237 ceed->refcount++; 238 (*rstr)->refcount = 1; 239 (*rstr)->nelem = nelem; 240 (*rstr)->elemsize = elemsize; 241 (*rstr)->nnodes = nnodes; 242 (*rstr)->ncomp = ncomp; 243 (*rstr)->nblk = nblk; 244 (*rstr)->blksize = blksize; 245 ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, 246 (const CeedInt *) blkindices, *rstr); 247 CeedChk(ierr); 248 249 if (cmode == CEED_OWN_POINTER) 250 ierr = CeedFree(&indices); CeedChk(ierr); 251 252 return 0; 253 } 254 255 /** 256 @brief Create CeedVectors associated with a CeedElemRestriction 257 258 @param rstr CeedElemRestriction 259 @param lvec The address of the L-vector to be created, or NULL 260 @param evec The address of the E-vector to be created, or NULL 261 262 @return An error code: 0 - success, otherwise - failure 263 264 @ref Advanced 265 **/ 266 int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *lvec, 267 CeedVector *evec) { 268 int ierr; 269 CeedInt n, m; 270 m = rstr->nnodes * rstr->ncomp; 271 n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp; 272 if (lvec) { 273 ierr = CeedVectorCreate(rstr->ceed, m, lvec); CeedChk(ierr); 274 } 275 if (evec) { 276 ierr = CeedVectorCreate(rstr->ceed, n, evec); CeedChk(ierr); 277 } 278 return 0; 279 } 280 281 /** 282 @brief Restrict an L-vector to an E-vector or apply transpose 283 284 @param rstr CeedElemRestriction 285 @param tmode Apply restriction or transpose 286 @param lmode Ordering of the ncomp components 287 @param u Input vector (of size @a nnodes * @a ncomp when 288 tmode=CEED_NOTRANSPOSE) 289 @param v Output vector (of size @a nelem * @a elemsize when 290 tmode=CEED_NOTRANSPOSE) 291 @param request Request or CEED_REQUEST_IMMEDIATE 292 293 @return An error code: 0 - success, otherwise - failure 294 295 @ref Advanced 296 **/ 297 int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode tmode, 298 CeedTransposeMode lmode, 299 CeedVector u, CeedVector v, CeedRequest *request) { 300 CeedInt m,n; 301 int ierr; 302 303 if (tmode == CEED_NOTRANSPOSE) { 304 m = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp; 305 n = rstr->nnodes * rstr->ncomp; 306 } else { 307 m = rstr->nnodes * rstr->ncomp; 308 n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp; 309 } 310 if (n != u->length) 311 return CeedError(rstr->ceed, 2, 312 "Input vector size %d not compatible with element restriction (%d, %d)", 313 u->length, m, n); 314 if (m != v->length) 315 return CeedError(rstr->ceed, 2, 316 "Output vector size %d not compatible with element restriction (%d, %d)", 317 v->length, m, n); 318 ierr = rstr->Apply(rstr, tmode, lmode, u, v, request); CeedChk(ierr); 319 320 return 0; 321 } 322 323 /** 324 @brief Restrict an L-vector to a block of an E-vector or apply transpose 325 326 @param rstr CeedElemRestriction 327 @param block Block number to restrict to/from, i.e. block=0 will handle 328 elements [0 : blksize] and block=3 will handle elements 329 [3*blksize : 4*blksize] 330 @param tmode Apply restriction or transpose 331 @param lmode Ordering of the ncomp components 332 @param u Input vector (of size @a nnodes * @a ncomp when 333 tmode=CEED_NOTRANSPOSE) 334 @param v Output vector (of size @a nelem * @a elemsize when 335 tmode=CEED_NOTRANSPOSE) 336 @param request Request or CEED_REQUEST_IMMEDIATE 337 338 @return An error code: 0 - success, otherwise - failure 339 340 @ref Advanced 341 **/ 342 int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, 343 CeedTransposeMode tmode, 344 CeedTransposeMode lmode, 345 CeedVector u, CeedVector v, 346 CeedRequest *request) { 347 CeedInt m,n; 348 int ierr; 349 350 if (tmode == CEED_NOTRANSPOSE) { 351 m = rstr->blksize * rstr->elemsize * rstr->ncomp; 352 n = rstr->nnodes * rstr->ncomp; 353 } else { 354 m = rstr->nnodes * rstr->ncomp; 355 n = rstr->blksize * rstr->elemsize * rstr->ncomp; 356 } 357 if (n != u->length) 358 return CeedError(rstr->ceed, 2, 359 "Input vector size %d not compatible with element restriction (%d, %d)", 360 u->length, m, n); 361 if (m != v->length) 362 return CeedError(rstr->ceed, 2, 363 "Output vector size %d not compatible with element restriction (%d, %d)", 364 v->length, m, n); 365 if (rstr->blksize*block > rstr->nelem) 366 return CeedError(rstr->ceed, 2, 367 "Cannot retrieve block %d, element %d > total elements %d", 368 block, rstr->blksize*block, rstr->nelem); 369 ierr = rstr->ApplyBlock(rstr, block, tmode, lmode, u, v, request); 370 CeedChk(ierr); 371 372 return 0; 373 } 374 375 /** 376 @brief Get the multiplicity of DoFs in a CeedElemRestriction 377 378 @param rstr CeedElemRestriction 379 @param[out] mult Vector to store multiplicity (of size ndof) 380 381 @return An error code: 0 - success, otherwise - failure 382 383 @ref Advanced 384 **/ 385 int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr, 386 CeedVector mult) { 387 int ierr; 388 CeedVector evec; 389 390 // Create and set evec 391 ierr = CeedElemRestrictionCreateVector(rstr, NULL, &evec); CeedChk(ierr); 392 ierr = CeedVectorSetValue(evec, 1.0); CeedChk(ierr); 393 394 // Apply to get multiplicity 395 ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, CEED_NOTRANSPOSE, evec, 396 mult, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 397 398 // Cleanup 399 ierr = CeedVectorDestroy(&evec); CeedChk(ierr); 400 401 return 0; 402 } 403 404 /** 405 @brief Get the Ceed associated with a CeedElemRestriction 406 407 @param rstr CeedElemRestriction 408 @param[out] ceed Variable to store Ceed 409 410 @return An error code: 0 - success, otherwise - failure 411 412 @ref Advanced 413 **/ 414 int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) { 415 *ceed = rstr->ceed; 416 return 0; 417 } 418 419 /** 420 @brief Get the total number of elements in the range of a CeedElemRestriction 421 422 @param rstr CeedElemRestriction 423 @param[out] numelements Variable to store number of elements 424 425 @return An error code: 0 - success, otherwise - failure 426 427 @ref Advanced 428 **/ 429 int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, 430 CeedInt *numelem) { 431 *numelem = rstr->nelem; 432 return 0; 433 } 434 435 /** 436 @brief Get the size of elements in the CeedElemRestriction 437 438 @param rstr CeedElemRestriction 439 @param[out] elemsize Variable to store size of elements 440 441 @return An error code: 0 - success, otherwise - failure 442 443 @ref Advanced 444 **/ 445 int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, 446 CeedInt *elemsize) { 447 *elemsize = rstr->elemsize; 448 return 0; 449 } 450 451 /** 452 @brief Get the number of degrees of freedom in the range of a 453 CeedElemRestriction 454 455 @param rstr CeedElemRestriction 456 @param[out] numnodes Variable to store number of nodes 457 458 @return An error code: 0 - success, otherwise - failure 459 460 @ref Advanced 461 **/ 462 int CeedElemRestrictionGetNumNodes(CeedElemRestriction rstr, 463 CeedInt *numnodes) { 464 *numnodes = rstr->nnodes; 465 return 0; 466 } 467 468 /** 469 @brief Get the number of components in the elements of a 470 CeedElemRestriction 471 472 @param rstr CeedElemRestriction 473 @param[out] numcomp Variable to store number of components 474 475 @return An error code: 0 - success, otherwise - failure 476 477 @ref Advanced 478 **/ 479 int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, 480 CeedInt *numcomp) { 481 *numcomp = rstr->ncomp; 482 return 0; 483 } 484 485 /** 486 @brief Get the number of blocks in a CeedElemRestriction 487 488 @param rstr CeedElemRestriction 489 @param[out] numblock Variable to store number of blocks 490 491 @return An error code: 0 - success, otherwise - failure 492 493 @ref Advanced 494 **/ 495 int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, 496 CeedInt *numblock) { 497 *numblock = rstr->nblk; 498 return 0; 499 } 500 501 /** 502 @brief Get the size of blocks in the CeedElemRestriction 503 504 @param r CeedElemRestriction 505 @param[out] blksize Variable to store size of blocks 506 507 @return An error code: 0 - success, otherwise - failure 508 509 @ref Advanced 510 **/ 511 int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, 512 CeedInt *blksize) { 513 *blksize = rstr->blksize; 514 return 0; 515 } 516 517 /** 518 @brief Get the backend data of a CeedElemRestriction 519 520 @param r CeedElemRestriction 521 @param[out] data Variable to store data 522 523 @return An error code: 0 - success, otherwise - failure 524 525 @ref Advanced 526 **/ 527 int CeedElemRestrictionGetData(CeedElemRestriction rstr, 528 void* *data) { 529 *data = rstr->data; 530 return 0; 531 } 532 533 /** 534 @brief Set the backend data of a CeedElemRestriction 535 536 @param[out] r CeedElemRestriction 537 @param data Data to set 538 539 @return An error code: 0 - success, otherwise - failure 540 541 @ref Advanced 542 **/ 543 int CeedElemRestrictionSetData(CeedElemRestriction rstr, 544 void* *data) { 545 rstr->data = *data; 546 return 0; 547 } 548 549 /** 550 @brief View a CeedElemRestriction 551 552 @param[in] rstr CeedElemRestriction to view 553 @param[in] stream Stream to write; typically stdout/stderr or a file 554 555 @return Error code: 0 - success, otherwise - failure 556 557 @ref Utility 558 **/ 559 int CeedElemRestrictionView(CeedElemRestriction rstr, FILE *stream) { 560 fprintf(stream, 561 "CeedElemRestriction from (%d, %d) to %d elements with %d nodes each\n", 562 rstr->nnodes, rstr->ncomp, rstr->nelem, rstr->elemsize); 563 return 0; 564 } 565 566 /** 567 @brief Destroy a CeedElemRestriction 568 569 @param rstr CeedElemRestriction to destroy 570 571 @return An error code: 0 - success, otherwise - failure 572 573 @ref Basic 574 **/ 575 int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) { 576 int ierr; 577 578 if (!*rstr || --(*rstr)->refcount > 0) return 0; 579 if ((*rstr)->Destroy) { 580 ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr); 581 } 582 ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr); 583 ierr = CeedFree(rstr); CeedChk(ierr); 584 return 0; 585 } 586 587 /// @} 588