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