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