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] r 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 *r) { 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, r); CeedChk(ierr); 65 return 0; 66 } 67 68 ierr = CeedCalloc(1, r); CeedChk(ierr); 69 (*r)->ceed = ceed; 70 ceed->refcount++; 71 (*r)->refcount = 1; 72 (*r)->nelem = nelem; 73 (*r)->elemsize = elemsize; 74 (*r)->ndof = ndof; 75 (*r)->ncomp = ncomp; 76 (*r)->nblk = nelem; 77 (*r)->blksize = 1; 78 ierr = ceed->ElemRestrictionCreate(mtype, cmode, indices, *r); 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 r 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 *r) { 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, r); CeedChk(ierr); 115 return 0; 116 } 117 118 ierr = CeedCalloc(1, r); CeedChk(ierr); 119 (*r)->ceed = ceed; 120 ceed->refcount++; 121 (*r)->refcount = 1; 122 (*r)->nelem = nelem; 123 (*r)->elemsize = elemsize; 124 (*r)->ndof = ndof; 125 (*r)->ncomp = ncomp; 126 (*r)->nblk = nelem; 127 (*r)->blksize = 1; 128 ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, *r); 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 r 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, CeedElemRestriction *r) { 194 int ierr; 195 CeedInt *blkindices; 196 CeedInt nblk = (nelem / blksize) + !!(nelem % blksize); 197 198 if (!ceed->ElemRestrictionCreateBlocked) { 199 Ceed delegate; 200 ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr); 201 202 if (!delegate) 203 return CeedError(ceed, 1, 204 "Backend does not support ElemRestrictionCreateBlocked"); 205 206 ierr = CeedElemRestrictionCreateBlocked(delegate, nelem, elemsize, 207 blksize, ndof, ncomp, mtype, cmode, 208 indices, r); CeedChk(ierr); 209 return 0; 210 } 211 212 ierr = CeedCalloc(1, r); CeedChk(ierr); 213 214 if (indices) { 215 ierr = CeedCalloc(nblk*blksize*elemsize, &blkindices); 216 ierr = CeedPermutePadIndices(indices, blkindices, nblk, nelem, blksize, 217 elemsize); 218 CeedChk(ierr); 219 } else { 220 blkindices = NULL; 221 } 222 223 (*r)->ceed = ceed; 224 ceed->refcount++; 225 (*r)->refcount = 1; 226 (*r)->nelem = nelem; 227 (*r)->elemsize = elemsize; 228 (*r)->ndof = ndof; 229 (*r)->ncomp = ncomp; 230 (*r)->nblk = nblk; 231 (*r)->blksize = blksize; 232 ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER, 233 (const CeedInt *) blkindices, *r); 234 CeedChk(ierr); 235 236 if (cmode == CEED_OWN_POINTER) 237 ierr = CeedFree(&indices); CeedChk(ierr); 238 239 return 0; 240 } 241 242 /** 243 @brief Create CeedVectors associated with a CeedElemRestriction 244 245 @param r CeedElemRestriction 246 @param lvec The address of the L-vector to be created, or NULL 247 @param evec The address of the E-vector to be created, or NULL 248 249 @return An error code: 0 - success, otherwise - failure 250 251 @ref Advanced 252 **/ 253 int CeedElemRestrictionCreateVector(CeedElemRestriction r, CeedVector *lvec, 254 CeedVector *evec) { 255 int ierr; 256 CeedInt n, m; 257 m = r->ndof * r->ncomp; 258 n = r->nblk * r->blksize * r->elemsize * r->ncomp; 259 if (lvec) { 260 ierr = CeedVectorCreate(r->ceed, m, lvec); CeedChk(ierr); 261 } 262 if (evec) { 263 ierr = CeedVectorCreate(r->ceed, n, evec); CeedChk(ierr); 264 } 265 return 0; 266 } 267 268 /** 269 @brief Restrict an L-vector to an E-vector or apply transpose 270 271 @param r CeedElemRestriction 272 @param tmode Apply restriction or transpose 273 @param lmode Ordering of the ncomp components 274 @param u Input vector (of size @a ndof when tmode=CEED_NOTRANSPOSE) 275 @param v Output vector (of size @a nelem * @a elemsize when tmode=CEED_NOTRANSPOSE) 276 @param request Request or CEED_REQUEST_IMMEDIATE 277 278 @return An error code: 0 - success, otherwise - failure 279 280 @ref Advanced 281 **/ 282 int CeedElemRestrictionApply(CeedElemRestriction r, CeedTransposeMode tmode, 283 CeedTransposeMode lmode, 284 CeedVector u, CeedVector v, CeedRequest *request) { 285 CeedInt m,n; 286 int ierr; 287 288 if (tmode == CEED_NOTRANSPOSE) { 289 m = r->nblk * r->blksize * r->elemsize * r->ncomp; 290 n = r->ndof * r->ncomp; 291 } else { 292 m = r->ndof * r->ncomp; 293 n = r->nblk * r->blksize * r->elemsize * r->ncomp; 294 } 295 if (n != u->length) 296 return CeedError(r->ceed, 2, 297 "Input vector size %d not compatible with element restriction (%d, %d)", 298 u->length, m, n); 299 if (m != v->length) 300 return CeedError(r->ceed, 2, 301 "Output vector size %d not compatible with element restriction (%d, %d)", 302 v->length, m, n); 303 ierr = r->Apply(r, tmode, lmode, u, v, request); CeedChk(ierr); 304 305 return 0; 306 } 307 308 /** 309 @brief Get the total number of elements in the range of a CeedElemRestriction 310 311 @param r CeedElemRestriction 312 @param[out] numelements Number of elements 313 314 @return An error code: 0 - success, otherwise - failure 315 316 @ref Utility 317 **/ 318 int CeedElemRestrictionGetNumElements(CeedElemRestriction r, 319 CeedInt *numelements) { 320 *numelements = r->nelem; 321 return 0; 322 } 323 324 /** 325 @brief Destroy a CeedElemRestriction 326 327 @param r CeedElemRestriction to destroy 328 329 @return An error code: 0 - success, otherwise - failure 330 331 @ref Basic 332 **/ 333 int CeedElemRestrictionDestroy(CeedElemRestriction *r) { 334 int ierr; 335 336 if (!*r || --(*r)->refcount > 0) return 0; 337 if ((*r)->Destroy) { 338 ierr = (*r)->Destroy(*r); CeedChk(ierr); 339 } 340 ierr = CeedDestroy(&(*r)->ceed); CeedChk(ierr); 341 ierr = CeedFree(r); CeedChk(ierr); 342 return 0; 343 } 344 345 /// @} 346