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