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 dimensions @a nelem × @a elemsize) using 39 column-major storage layout. 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] r 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 *r) { 54 int ierr; 55 56 if (!ceed->ElemRestrictionCreate) 57 return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate"); 58 ierr = CeedCalloc(1, r); CeedChk(ierr); 59 (*r)->ceed = ceed; 60 ceed->refcount++; 61 (*r)->refcount = 1; 62 (*r)->nelem = nelem; 63 (*r)->elemsize = elemsize; 64 (*r)->ndof = ndof; 65 (*r)->ncomp = ncomp; 66 (*r)->nblk = nelem; 67 (*r)->blksize = 1; 68 ierr = ceed->ElemRestrictionCreate(*r, mtype, cmode, indices); CeedChk(ierr); 69 return 0; 70 } 71 72 /** 73 @brief Create an identity CeedElemRestriction 74 75 @param ceed A Ceed object where the CeedElemRestriction will be created 76 @param nelem Number of elements described in the @a indices array 77 @param elemsize Size (number of "nodes") per element 78 @param ndof The total size of the input CeedVector to which the 79 restriction will be applied. This size may include data 80 used by other CeedElemRestriction objects describing 81 different types of elements 82 @param ncomp Number of field components per interpolation node 83 @param r Address of the variable where the newly created 84 CeedElemRestriction will be stored 85 86 @return An error code: 0 - success, otherwise - failure 87 88 @ref Basic 89 **/ 90 int CeedElemRestrictionCreateIdentity(Ceed ceed, CeedInt nelem, CeedInt elemsize, 91 CeedInt ndof, CeedInt ncomp, CeedElemRestriction *r) { 92 int ierr; 93 94 if (!ceed->ElemRestrictionCreate) 95 return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreateIdentity"); 96 ierr = CeedCalloc(1, r); CeedChk(ierr); 97 (*r)->ceed = ceed; 98 ceed->refcount++; 99 (*r)->refcount = 1; 100 (*r)->nelem = nelem; 101 (*r)->elemsize = elemsize; 102 (*r)->ndof = ndof; 103 (*r)->ncomp = ncomp; 104 (*r)->nblk = nelem; 105 (*r)->blksize = 1; 106 ierr = ceed->ElemRestrictionCreate(*r, CEED_MEM_HOST, CEED_OWN_POINTER, NULL); CeedChk(ierr); 107 return 0; 108 } 109 110 /** 111 @brief Permute and pad indices for a blocked restriction 112 113 @param indices Array of dimensions @a nelem × @a elemsize) using 114 row-major storage layout. Row i holds the ordered list 115 of the indices (into the input CeedVector) for the unknowns 116 corresponding to element i, where 0 <= i < @a nelements. 117 All indices must be in the range [0, @a ndof). 118 @param blkindices Array of permuted and padded indicies size 119 @a nblk × @a blksize × @a elemsize using row-major ordering. 120 @param nblk Number of blocks 121 @param nelem Number of elements 122 @param blksize Number of elements in a block 123 @param elemsize Size of each element 124 125 @return An error code: 0 - success, otherwise - failure 126 127 @ref Utility 128 **/ 129 int CeedPermutePadIndices(const CeedInt *indices, CeedInt *blkindices, 130 CeedInt nblk, CeedInt nelem, 131 CeedInt blksize, CeedInt elemsize) { 132 for (CeedInt e = 0; e < nblk*blksize; e+=blksize) 133 for (int j = 0; j < blksize; j++) 134 for (int k = 0; k < elemsize; k++) 135 blkindices[e*elemsize + k*blksize + j] 136 = indices[CeedIntMin(e+j,nelem-1)*elemsize + k]; 137 return 0; 138 } 139 140 /** 141 @brief Create a blocked CeedElemRestriction, typically only called by backends 142 143 @param ceed A Ceed object where the CeedElemRestriction will be created. 144 @param nelem Number of elements described in the @a indices array. 145 @param elemsize Size (number of unknowns) per element 146 @param blksize Number of elements in a block 147 @param ndof The total size of the input CeedVector to which the 148 restriction will be applied. This size may include data 149 used by other CeedElemRestriction objects describing 150 different types of elements. 151 @param ncomp Number of components stored at each node 152 @param mtype Memory type of the @a indices array, see CeedMemType 153 @param cmode Copy mode for the @a indices array, see CeedCopyMode 154 @param indices Array of dimensions @a nelem × @a elemsize) using 155 column-major storage layout. Row i holds the ordered list 156 of the indices (into the input CeedVector) for the unknowns 157 corresponding to element i, where 0 <= i < @a nelements. 158 All indices must be in the range [0, @a ndof). The 159 backend will permute and pad this array to the desired 160 ordering for the blocksize, which is typically given by the 161 backend. The default reordering is to interlace elements. 162 @param r Address of the variable where the newly created 163 CeedElemRestriction will be stored 164 165 @return An error code: 0 - success, otherwise - failure 166 167 @ref Advanced 168 **/ 169 int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt nelem, CeedInt elemsize, 170 CeedInt blksize, CeedInt ndof, CeedInt ncomp, 171 CeedMemType mtype, CeedCopyMode cmode, 172 const CeedInt *indices, CeedElemRestriction *r) { 173 int ierr; 174 CeedInt *blkindices; 175 CeedInt nblk = (nelem / blksize) + !!(nelem % blksize); 176 177 if (!ceed->ElemRestrictionCreateBlocked) 178 return CeedError(ceed, 1, 179 "Backend does not support ElemRestrictionCreateBlocked"); 180 if (mtype != CEED_MEM_HOST) 181 return CeedError(ceed, 1, "Only MemType = HOST supported"); 182 183 ierr = CeedCalloc(1, r); CeedChk(ierr); 184 185 if (indices) { 186 ierr = CeedCalloc(nblk*blksize*elemsize, &blkindices); 187 ierr = CeedPermutePadIndices(indices, blkindices, nblk, nelem, blksize, elemsize); 188 CeedChk(ierr); 189 } else { 190 blkindices = NULL; 191 } 192 193 (*r)->ceed = ceed; 194 ceed->refcount++; 195 (*r)->refcount = 1; 196 (*r)->nelem = nelem; 197 (*r)->elemsize = elemsize; 198 (*r)->ndof = ndof; 199 (*r)->ncomp = ncomp; 200 (*r)->nblk = nblk; 201 (*r)->blksize = blksize; 202 ierr = ceed->ElemRestrictionCreateBlocked(*r, CEED_MEM_HOST, CEED_OWN_POINTER, 203 (const CeedInt *) blkindices); 204 CeedChk(ierr); 205 206 if (cmode == CEED_OWN_POINTER) 207 ierr = CeedFree(&indices); CeedChk(ierr); 208 209 return 0; 210 } 211 212 /** 213 @brief Create CeedVectors associated with a CeedElemRestriction 214 215 @param r CeedElemRestriction 216 @param lvec The address of the L-vector to be created, or NULL 217 @param evec The address of the E-vector to be created, or NULL 218 219 @return An error code: 0 - success, otherwise - failure 220 221 @ref Advanced 222 **/ 223 int CeedElemRestrictionCreateVector(CeedElemRestriction r, CeedVector *lvec, 224 CeedVector *evec) { 225 int ierr; 226 CeedInt n, m; 227 m = r->ndof * r->ncomp; 228 n = r->nblk * r->blksize * r->elemsize * r->ncomp; 229 if (lvec) { 230 ierr = CeedVectorCreate(r->ceed, m, lvec); CeedChk(ierr); 231 } 232 if (evec) { 233 ierr = CeedVectorCreate(r->ceed, n, evec); CeedChk(ierr); 234 } 235 return 0; 236 } 237 238 /** 239 @brief Restrict an L-vector to an E-vector or apply transpose 240 241 @param r CeedElemRestriction 242 @param tmode Apply restriction or transpose 243 @param lmode Ordering of the ncomp components 244 @param u Input vector (of size @a ndof when tmode=CEED_NOTRANSPOSE) 245 @param v Output vector (of size @a nelem * @a elemsize when tmode=CEED_NOTRANSPOSE) 246 @param request Request or CEED_REQUEST_IMMEDIATE 247 248 @return An error code: 0 - success, otherwise - failure 249 250 @ref Advanced 251 **/ 252 int CeedElemRestrictionApply(CeedElemRestriction r, CeedTransposeMode tmode, 253 CeedTransposeMode lmode, 254 CeedVector u, CeedVector v, CeedRequest *request) { 255 CeedInt m,n; 256 int ierr; 257 258 if (tmode == CEED_NOTRANSPOSE) { 259 m = r->nblk * r->blksize * r->elemsize * r->ncomp; 260 n = r->ndof * r->ncomp; 261 } else { 262 m = r->ndof * r->ncomp; 263 n = r->nblk * r->blksize * r->elemsize * r->ncomp; 264 } 265 if (n != u->length) 266 return CeedError(r->ceed, 2, 267 "Input vector size %d not compatible with element restriction (%d, %d)", 268 u->length, m, n); 269 if (m != v->length) 270 return CeedError(r->ceed, 2, 271 "Output vector size %d not compatible with element restriction (%d, %d)", 272 v->length, m, n); 273 ierr = r->Apply(r, tmode, lmode, u, v, request); CeedChk(ierr); 274 275 return 0; 276 } 277 278 /** 279 @brief Get the total number of elements in the range of a CeedElemRestriction 280 281 @param r CeedElemRestriction 282 @param[out] numelements Number of elements 283 284 @return An error code: 0 - success, otherwise - failure 285 286 @ref Utility 287 **/ 288 int CeedElemRestrictionGetNumElements(CeedElemRestriction r, 289 CeedInt *numelements) { 290 *numelements = r->nelem; 291 return 0; 292 } 293 294 /** 295 @brief Destroy a CeedElemRestriction 296 297 @param r CeedElemRestriction to destroy 298 299 @return An error code: 0 - success, otherwise - failure 300 301 @ref Basic 302 **/ 303 int CeedElemRestrictionDestroy(CeedElemRestriction *r) { 304 int ierr; 305 306 if (!*r || --(*r)->refcount > 0) return 0; 307 if ((*r)->Destroy) { 308 ierr = (*r)->Destroy(*r); CeedChk(ierr); 309 } 310 ierr = CeedDestroy(&(*r)->ceed); CeedChk(ierr); 311 ierr = CeedFree(r); CeedChk(ierr); 312 return 0; 313 } 314 315 /// @} 316