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