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