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