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