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 Get the Ceed associated with a CeedElemRestriction 313 314 @param rstr CeedElemRestriction 315 @param[out] ceed Variable to store Ceed 316 317 @return An error code: 0 - success, otherwise - failure 318 319 @ref Advanced 320 **/ 321 int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) { 322 *ceed = rstr->ceed; 323 return 0; 324 } 325 326 /** 327 @brief Get the total number of elements in the range of a CeedElemRestriction 328 329 @param rstr CeedElemRestriction 330 @param[out] numelements Variable to store number of elements 331 332 @return An error code: 0 - success, otherwise - failure 333 334 @ref Advanced 335 **/ 336 int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr, 337 CeedInt *numelem) { 338 *numelem = rstr->nelem; 339 return 0; 340 } 341 342 /** 343 @brief Get the size of elements in the CeedElemRestriction 344 345 @param rstr CeedElemRestriction 346 @param[out] elemsize Variable to store size of elements 347 348 @return An error code: 0 - success, otherwise - failure 349 350 @ref Advanced 351 **/ 352 int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr, 353 CeedInt *elemsize) { 354 *elemsize = rstr->elemsize; 355 return 0; 356 } 357 358 /** 359 @brief Get the number of degrees of freedom in the range of a 360 CeedElemRestriction 361 362 @param rstr CeedElemRestriction 363 @param[out] numdof Variable to store number of DoFs 364 365 @return An error code: 0 - success, otherwise - failure 366 367 @ref Advanced 368 **/ 369 int CeedElemRestrictionGetNumDoF(CeedElemRestriction rstr, 370 CeedInt *numdof) { 371 *numdof = rstr->ndof; 372 return 0; 373 } 374 375 /** 376 @brief Get the number of components in the elements of a 377 CeedElemRestriction 378 379 @param rstr CeedElemRestriction 380 @param[out] numcomp Variable to store number of components 381 382 @return An error code: 0 - success, otherwise - failure 383 384 @ref Advanced 385 **/ 386 int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr, 387 CeedInt *numcomp) { 388 *numcomp = rstr->ncomp; 389 return 0; 390 } 391 392 /** 393 @brief Get the number of blocks in a CeedElemRestriction 394 395 @param rstr CeedElemRestriction 396 @param[out] numblock Variable to store number of blocks 397 398 @return An error code: 0 - success, otherwise - failure 399 400 @ref Advanced 401 **/ 402 int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr, 403 CeedInt *numblock) { 404 *numblock = rstr->nblk; 405 return 0; 406 } 407 408 /** 409 @brief Get the size of blocks in the CeedElemRestriction 410 411 @param r CeedElemRestriction 412 @param[out] blksize Variable to store size of blocks 413 414 @return An error code: 0 - success, otherwise - failure 415 416 @ref Advanced 417 **/ 418 int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr, 419 CeedInt *blksize) { 420 *blksize = rstr->blksize; 421 return 0; 422 } 423 424 /** 425 @brief Get the backend data of a CeedElemRestriction 426 427 @param r CeedElemRestriction 428 @param[out] data Variable to store data 429 430 @return An error code: 0 - success, otherwise - failure 431 432 @ref Advanced 433 **/ 434 int CeedElemRestrictionGetData(CeedElemRestriction rstr, 435 void* *data) { 436 *data = rstr->data; 437 return 0; 438 } 439 440 /** 441 @brief Set the backend data of a CeedElemRestriction 442 443 @param[out] r CeedElemRestriction 444 @param data Data to set 445 446 @return An error code: 0 - success, otherwise - failure 447 448 @ref Advanced 449 **/ 450 int CeedElemRestrictionSetData(CeedElemRestriction rstr, 451 void* *data) { 452 rstr->data = *data; 453 return 0; 454 } 455 456 /** 457 @brief Destroy a CeedElemRestriction 458 459 @param rstr CeedElemRestriction to destroy 460 461 @return An error code: 0 - success, otherwise - failure 462 463 @ref Basic 464 **/ 465 int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) { 466 int ierr; 467 468 if (!*rstr || --(*rstr)->refcount > 0) return 0; 469 if ((*rstr)->Destroy) { 470 ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr); 471 } 472 ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr); 473 ierr = CeedFree(rstr); CeedChk(ierr); 474 return 0; 475 } 476 477 /// @} 478