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