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 Ceed associated with a CeedElemRestriction 366 367 @param rstr CeedElemRestriction 368 @param[out] ceed Variable to store Ceed 369 370 @return An error code: 0 - success, otherwise - failure 371 372 @ref Advanced 373 **/ 374 int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) { 375 *ceed = rstr->ceed; 376 return 0; 377 } 378 379 /** 380 @brief Get the total number of elements in the range of a CeedElemRestriction 381 382 @param rstr CeedElemRestriction 383 @param[out] numelements Variable to store number of elements 384 385 @return An error code: 0 - success, otherwise - failure 386 387 @ref Advanced 388 **/ 389 int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, 390 CeedInt *numelem) { 391 *numelem = rstr->nelem; 392 return 0; 393 } 394 395 /** 396 @brief Get the size of elements in the CeedElemRestriction 397 398 @param rstr CeedElemRestriction 399 @param[out] elemsize Variable to store size of elements 400 401 @return An error code: 0 - success, otherwise - failure 402 403 @ref Advanced 404 **/ 405 int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, 406 CeedInt *elemsize) { 407 *elemsize = rstr->elemsize; 408 return 0; 409 } 410 411 /** 412 @brief Get the number of degrees of freedom in the range of a 413 CeedElemRestriction 414 415 @param rstr CeedElemRestriction 416 @param[out] numdof Variable to store number of DoFs 417 418 @return An error code: 0 - success, otherwise - failure 419 420 @ref Advanced 421 **/ 422 int CeedElemRestrictionGetNumDoF(CeedElemRestriction rstr, 423 CeedInt *numdof) { 424 *numdof = rstr->ndof; 425 return 0; 426 } 427 428 /** 429 @brief Get the number of components in the elements of a 430 CeedElemRestriction 431 432 @param rstr CeedElemRestriction 433 @param[out] numcomp Variable to store number of components 434 435 @return An error code: 0 - success, otherwise - failure 436 437 @ref Advanced 438 **/ 439 int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, 440 CeedInt *numcomp) { 441 *numcomp = rstr->ncomp; 442 return 0; 443 } 444 445 /** 446 @brief Get the number of blocks in a CeedElemRestriction 447 448 @param rstr CeedElemRestriction 449 @param[out] numblock Variable to store number of blocks 450 451 @return An error code: 0 - success, otherwise - failure 452 453 @ref Advanced 454 **/ 455 int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, 456 CeedInt *numblock) { 457 *numblock = rstr->nblk; 458 return 0; 459 } 460 461 /** 462 @brief Get the size of blocks in the CeedElemRestriction 463 464 @param r CeedElemRestriction 465 @param[out] blksize Variable to store size of blocks 466 467 @return An error code: 0 - success, otherwise - failure 468 469 @ref Advanced 470 **/ 471 int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, 472 CeedInt *blksize) { 473 *blksize = rstr->blksize; 474 return 0; 475 } 476 477 /** 478 @brief Get the backend data of a CeedElemRestriction 479 480 @param r CeedElemRestriction 481 @param[out] data Variable to store data 482 483 @return An error code: 0 - success, otherwise - failure 484 485 @ref Advanced 486 **/ 487 int CeedElemRestrictionGetData(CeedElemRestriction rstr, 488 void* *data) { 489 *data = rstr->data; 490 return 0; 491 } 492 493 /** 494 @brief Set the backend data of a CeedElemRestriction 495 496 @param[out] r CeedElemRestriction 497 @param data Data to set 498 499 @return An error code: 0 - success, otherwise - failure 500 501 @ref Advanced 502 **/ 503 int CeedElemRestrictionSetData(CeedElemRestriction rstr, 504 void* *data) { 505 rstr->data = *data; 506 return 0; 507 } 508 509 /** 510 @brief Destroy a CeedElemRestriction 511 512 @param rstr CeedElemRestriction to destroy 513 514 @return An error code: 0 - success, otherwise - failure 515 516 @ref Basic 517 **/ 518 int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) { 519 int ierr; 520 521 if (!*rstr || --(*rstr)->refcount > 0) return 0; 522 if ((*rstr)->Destroy) { 523 ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr); 524 } 525 ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr); 526 ierr = CeedFree(rstr); CeedChk(ierr); 527 return 0; 528 } 529 530 /// @} 531