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