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