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 316 @param tmode Apply restriction or transpose 317 @param lmode Ordering of the ncomp components 318 @param u Input vector (of size @a ndof when tmode=CEED_NOTRANSPOSE) 319 @param v Output vector (of size @a nelem * @a elemsize when tmode=CEED_NOTRANSPOSE) 320 @param request Request or CEED_REQUEST_IMMEDIATE 321 322 @return An error code: 0 - success, otherwise - failure 323 324 @ref Advanced 325 **/ 326 int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block, 327 CeedTransposeMode tmode, 328 CeedTransposeMode lmode, 329 CeedVector u, CeedVector v, 330 CeedRequest *request) { 331 CeedInt m,n; 332 int ierr; 333 334 if (tmode == CEED_NOTRANSPOSE) { 335 m = rstr->blksize * rstr->elemsize * rstr->ncomp; 336 n = rstr->ndof * rstr->ncomp; 337 } else { 338 m = rstr->ndof * rstr->ncomp; 339 n = rstr->blksize * rstr->elemsize * rstr->ncomp; 340 } 341 if (n != u->length) 342 return CeedError(rstr->ceed, 2, 343 "Input vector size %d not compatible with element restriction (%d, %d)", 344 u->length, m, n); 345 if (m != v->length) 346 return CeedError(rstr->ceed, 2, 347 "Output vector size %d not compatible with element restriction (%d, %d)", 348 v->length, m, n); 349 if (rstr->blksize*block > rstr->nelem) 350 return CeedError(rstr->ceed, 2, 351 "Cannot retrieve block %d, element %d > total elements %d", 352 block, rstr->blksize*block, rstr->nelem); 353 ierr = rstr->ApplyBlock(rstr, block, tmode, lmode, u, v, request); 354 CeedChk(ierr); 355 356 return 0; 357 } 358 359 /** 360 @brief Get the Ceed associated with a CeedElemRestriction 361 362 @param rstr CeedElemRestriction 363 @param[out] ceed Variable to store Ceed 364 365 @return An error code: 0 - success, otherwise - failure 366 367 @ref Advanced 368 **/ 369 int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) { 370 *ceed = rstr->ceed; 371 return 0; 372 } 373 374 /** 375 @brief Get the total number of elements in the range of a CeedElemRestriction 376 377 @param rstr CeedElemRestriction 378 @param[out] numelements Variable to store number of elements 379 380 @return An error code: 0 - success, otherwise - failure 381 382 @ref Advanced 383 **/ 384 int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, 385 CeedInt *numelem) { 386 *numelem = rstr->nelem; 387 return 0; 388 } 389 390 /** 391 @brief Get the size of elements in the CeedElemRestriction 392 393 @param rstr CeedElemRestriction 394 @param[out] elemsize Variable to store size of elements 395 396 @return An error code: 0 - success, otherwise - failure 397 398 @ref Advanced 399 **/ 400 int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, 401 CeedInt *elemsize) { 402 *elemsize = rstr->elemsize; 403 return 0; 404 } 405 406 /** 407 @brief Get the number of degrees of freedom in the range of a 408 CeedElemRestriction 409 410 @param rstr CeedElemRestriction 411 @param[out] numdof Variable to store number of DoFs 412 413 @return An error code: 0 - success, otherwise - failure 414 415 @ref Advanced 416 **/ 417 int CeedElemRestrictionGetNumDoF(CeedElemRestriction rstr, 418 CeedInt *numdof) { 419 *numdof = rstr->ndof; 420 return 0; 421 } 422 423 /** 424 @brief Get the number of components in the elements of a 425 CeedElemRestriction 426 427 @param rstr CeedElemRestriction 428 @param[out] numcomp Variable to store number of components 429 430 @return An error code: 0 - success, otherwise - failure 431 432 @ref Advanced 433 **/ 434 int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, 435 CeedInt *numcomp) { 436 *numcomp = rstr->ncomp; 437 return 0; 438 } 439 440 /** 441 @brief Get the number of blocks in a CeedElemRestriction 442 443 @param rstr CeedElemRestriction 444 @param[out] numblock Variable to store number of blocks 445 446 @return An error code: 0 - success, otherwise - failure 447 448 @ref Advanced 449 **/ 450 int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, 451 CeedInt *numblock) { 452 *numblock = rstr->nblk; 453 return 0; 454 } 455 456 /** 457 @brief Get the size of blocks in the CeedElemRestriction 458 459 @param r CeedElemRestriction 460 @param[out] blksize Variable to store size of blocks 461 462 @return An error code: 0 - success, otherwise - failure 463 464 @ref Advanced 465 **/ 466 int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, 467 CeedInt *blksize) { 468 *blksize = rstr->blksize; 469 return 0; 470 } 471 472 /** 473 @brief Get the backend data of a CeedElemRestriction 474 475 @param r CeedElemRestriction 476 @param[out] data Variable to store data 477 478 @return An error code: 0 - success, otherwise - failure 479 480 @ref Advanced 481 **/ 482 int CeedElemRestrictionGetData(CeedElemRestriction rstr, 483 void* *data) { 484 *data = rstr->data; 485 return 0; 486 } 487 488 /** 489 @brief Set the backend data of a CeedElemRestriction 490 491 @param[out] r CeedElemRestriction 492 @param data Data to set 493 494 @return An error code: 0 - success, otherwise - failure 495 496 @ref Advanced 497 **/ 498 int CeedElemRestrictionSetData(CeedElemRestriction rstr, 499 void* *data) { 500 rstr->data = *data; 501 return 0; 502 } 503 504 /** 505 @brief Destroy a CeedElemRestriction 506 507 @param rstr CeedElemRestriction to destroy 508 509 @return An error code: 0 - success, otherwise - failure 510 511 @ref Basic 512 **/ 513 int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) { 514 int ierr; 515 516 if (!*rstr || --(*rstr)->refcount > 0) return 0; 517 if ((*rstr)->Destroy) { 518 ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr); 519 } 520 ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr); 521 ierr = CeedFree(rstr); CeedChk(ierr); 522 return 0; 523 } 524 525 /// @} 526