1d7b241e6Sjeremylt // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2d7b241e6Sjeremylt // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3d7b241e6Sjeremylt // reserved. See files LICENSE and NOTICE for details. 4d7b241e6Sjeremylt // 5d7b241e6Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software 6d7b241e6Sjeremylt // libraries and APIs for efficient high-order finite element and spectral 7d7b241e6Sjeremylt // element discretizations for exascale applications. For more information and 8d7b241e6Sjeremylt // source code availability see http://github.com/ceed. 9d7b241e6Sjeremylt // 10d7b241e6Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11d7b241e6Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office 12d7b241e6Sjeremylt // of Science and the National Nuclear Security Administration) responsible for 13d7b241e6Sjeremylt // the planning and preparation of a capable exascale ecosystem, including 14d7b241e6Sjeremylt // software, applications, hardware, advanced system engineering and early 15d7b241e6Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative. 16d7b241e6Sjeremylt 17d7b241e6Sjeremylt #include <ceed-impl.h> 18d7b241e6Sjeremylt 19d7b241e6Sjeremylt /// @file 20d7b241e6Sjeremylt /// Implementation of public CeedElemRestriction interfaces 21d7b241e6Sjeremylt /// 22*dfdf5a53Sjeremylt /// @addtogroup CeedElemRestriction 23d7b241e6Sjeremylt /// @{ 24d7b241e6Sjeremylt 25d7b241e6Sjeremylt /** 26b11c1e72Sjeremylt @brief Create a CeedElemRestriction 27d7b241e6Sjeremylt 28b11c1e72Sjeremylt @param ceed A Ceed object where the CeedElemRestriction will be created 29b11c1e72Sjeremylt @param nelem Number of elements described in the @a indices array 30b11c1e72Sjeremylt @param elemsize Size (number of "nodes") per element 31d7b241e6Sjeremylt @param ndof The total size of the input CeedVector to which the 32d7b241e6Sjeremylt restriction will be applied. This size may include data 33d7b241e6Sjeremylt used by other CeedElemRestriction objects describing 34d7b241e6Sjeremylt different types of elements. 35b11c1e72Sjeremylt @param ncomp Number of field components per interpolation node 36b11c1e72Sjeremylt @param mtype Memory type of the @a indices array, see CeedMemType 37b11c1e72Sjeremylt @param cmode Copy mode for the @a indices array, see CeedCopyMode 38d7b241e6Sjeremylt @param indices Array of dimensions @a nelem × @a elemsize) using 39d7b241e6Sjeremylt column-major storage layout. Row i holds the ordered list 40d7b241e6Sjeremylt of the indices (into the input CeedVector) for the unknowns 41d7b241e6Sjeremylt corresponding to element i, where 0 <= i < @a nelements. 42d7b241e6Sjeremylt All indices must be in the range [0, @a ndof). 43b11c1e72Sjeremylt @param[out] r Address of the variable where the newly created 44b11c1e72Sjeremylt CeedElemRestriction will be stored 45d7b241e6Sjeremylt 46b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 47*dfdf5a53Sjeremylt 48*dfdf5a53Sjeremylt @ref Basic 49b11c1e72Sjeremylt **/ 50d7b241e6Sjeremylt int CeedElemRestrictionCreate(Ceed ceed, CeedInt nelem, CeedInt elemsize, 51d7b241e6Sjeremylt CeedInt ndof, CeedInt ncomp, CeedMemType mtype, 52d7b241e6Sjeremylt CeedCopyMode cmode, const CeedInt *indices, 53d7b241e6Sjeremylt CeedElemRestriction *r) { 54d7b241e6Sjeremylt int ierr; 55d7b241e6Sjeremylt 56d7b241e6Sjeremylt if (!ceed->ElemRestrictionCreate) 57d7b241e6Sjeremylt return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate"); 58d7b241e6Sjeremylt ierr = CeedCalloc(1, r); CeedChk(ierr); 59d7b241e6Sjeremylt (*r)->ceed = ceed; 60d7b241e6Sjeremylt ceed->refcount++; 61d7b241e6Sjeremylt (*r)->refcount = 1; 62d7b241e6Sjeremylt (*r)->nelem = nelem; 63d7b241e6Sjeremylt (*r)->elemsize = elemsize; 64d7b241e6Sjeremylt (*r)->ndof = ndof; 65d7b241e6Sjeremylt (*r)->ncomp = ncomp; 66d7b241e6Sjeremylt (*r)->nblk = nelem; 67d7b241e6Sjeremylt (*r)->blksize = 1; 68d7b241e6Sjeremylt ierr = ceed->ElemRestrictionCreate(*r, mtype, cmode, indices); CeedChk(ierr); 69d7b241e6Sjeremylt return 0; 70d7b241e6Sjeremylt } 71d7b241e6Sjeremylt 72d7b241e6Sjeremylt /** 73b11c1e72Sjeremylt @brief Create an identity CeedElemRestriction 74d7b241e6Sjeremylt 75b11c1e72Sjeremylt @param ceed A Ceed object where the CeedElemRestriction will be created 76b11c1e72Sjeremylt @param nelem Number of elements described in the @a indices array 77b11c1e72Sjeremylt @param elemsize Size (number of "nodes") per element 78d7b241e6Sjeremylt @param ndof The total size of the input CeedVector to which the 79d7b241e6Sjeremylt restriction will be applied. This size may include data 80d7b241e6Sjeremylt used by other CeedElemRestriction objects describing 81b11c1e72Sjeremylt different types of elements 82b11c1e72Sjeremylt @param ncomp Number of field components per interpolation node 83b11c1e72Sjeremylt @param r Address of the variable where the newly created 84b11c1e72Sjeremylt CeedElemRestriction will be stored 85d7b241e6Sjeremylt 86b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 87*dfdf5a53Sjeremylt 88*dfdf5a53Sjeremylt @ref Basic 89b11c1e72Sjeremylt **/ 90d7b241e6Sjeremylt int CeedElemRestrictionCreateIdentity(Ceed ceed, CeedInt nelem, CeedInt elemsize, 91d7b241e6Sjeremylt CeedInt ndof, CeedInt ncomp, CeedElemRestriction *r) { 92d7b241e6Sjeremylt int ierr; 93d7b241e6Sjeremylt 94d7b241e6Sjeremylt if (!ceed->ElemRestrictionCreate) 95d7b241e6Sjeremylt return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreateIdentity"); 96d7b241e6Sjeremylt ierr = CeedCalloc(1, r); CeedChk(ierr); 97d7b241e6Sjeremylt (*r)->ceed = ceed; 98d7b241e6Sjeremylt ceed->refcount++; 99d7b241e6Sjeremylt (*r)->refcount = 1; 100d7b241e6Sjeremylt (*r)->nelem = nelem; 101d7b241e6Sjeremylt (*r)->elemsize = elemsize; 102d7b241e6Sjeremylt (*r)->ndof = ndof; 103d7b241e6Sjeremylt (*r)->ncomp = ncomp; 104d7b241e6Sjeremylt (*r)->nblk = nelem; 105d7b241e6Sjeremylt (*r)->blksize = 1; 106d7b241e6Sjeremylt ierr = ceed->ElemRestrictionCreate(*r, CEED_MEM_HOST, CEED_OWN_POINTER, NULL); CeedChk(ierr); 107d7b241e6Sjeremylt return 0; 108d7b241e6Sjeremylt } 109d7b241e6Sjeremylt 110d7b241e6Sjeremylt /** 111b11c1e72Sjeremylt @brief Permute and pad indices for a blocked restriction 112d7b241e6Sjeremylt 113d7b241e6Sjeremylt @param indices Array of dimensions @a nelem × @a elemsize) using 114d7b241e6Sjeremylt row-major storage layout. Row i holds the ordered list 115d7b241e6Sjeremylt of the indices (into the input CeedVector) for the unknowns 116d7b241e6Sjeremylt corresponding to element i, where 0 <= i < @a nelements. 117d7b241e6Sjeremylt All indices must be in the range [0, @a ndof). 118d7b241e6Sjeremylt @param blkindices Array of permuted and padded indicies size 119b11c1e72Sjeremylt @a nblk × @a blksize × @a elemsize using row-major ordering. 120d7b241e6Sjeremylt @param nblk Number of blocks 121d7b241e6Sjeremylt @param nelem Number of elements 122d7b241e6Sjeremylt @param blksize Number of elements in a block 123d7b241e6Sjeremylt @param elemsize Size of each element 124d7b241e6Sjeremylt 125b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 126b11c1e72Sjeremylt 127*dfdf5a53Sjeremylt @ref Utility 128b11c1e72Sjeremylt **/ 129*dfdf5a53Sjeremylt int CeedPermutePadIndices(const CeedInt *indices, CeedInt *blkindices, 130d7b241e6Sjeremylt CeedInt nblk, CeedInt nelem, 131d7b241e6Sjeremylt CeedInt blksize, CeedInt elemsize) { 132d7b241e6Sjeremylt for (CeedInt e = 0; e < nblk*blksize; e+=blksize) 133d7b241e6Sjeremylt for (int j = 0; j < blksize; j++) 134d7b241e6Sjeremylt for (int k = 0; k < elemsize; k++) 135d7b241e6Sjeremylt blkindices[e*elemsize + k*blksize + j] 136d7b241e6Sjeremylt = indices[CeedIntMin(e+j,nelem-1)*elemsize + k]; 137*dfdf5a53Sjeremylt return 0; 138d7b241e6Sjeremylt } 139d7b241e6Sjeremylt 140d7b241e6Sjeremylt /** 141b11c1e72Sjeremylt @brief Create a blocked CeedElemRestriction, typically only called by backends 142d7b241e6Sjeremylt 143d7b241e6Sjeremylt @param ceed A Ceed object where the CeedElemRestriction will be created. 144d7b241e6Sjeremylt @param nelem Number of elements described in the @a indices array. 145b11c1e72Sjeremylt @param elemsize Size (number of unknowns) per element 146b11c1e72Sjeremylt @param blksize Number of elements in a block 147d7b241e6Sjeremylt @param ndof The total size of the input CeedVector to which the 148d7b241e6Sjeremylt restriction will be applied. This size may include data 149d7b241e6Sjeremylt used by other CeedElemRestriction objects describing 150d7b241e6Sjeremylt different types of elements. 151b11c1e72Sjeremylt @param ncomp Number of components stored at each node 152b11c1e72Sjeremylt @param mtype Memory type of the @a indices array, see CeedMemType 153b11c1e72Sjeremylt @param cmode Copy mode for the @a indices array, see CeedCopyMode 154d7b241e6Sjeremylt @param indices Array of dimensions @a nelem × @a elemsize) using 155d7b241e6Sjeremylt column-major storage layout. Row i holds the ordered list 156d7b241e6Sjeremylt of the indices (into the input CeedVector) for the unknowns 157d7b241e6Sjeremylt corresponding to element i, where 0 <= i < @a nelements. 158d7b241e6Sjeremylt All indices must be in the range [0, @a ndof). The 159d7b241e6Sjeremylt backend will permute and pad this array to the desired 160d7b241e6Sjeremylt ordering for the blocksize, which is typically given by the 161d7b241e6Sjeremylt backend. The default reordering is to interlace elements. 162b11c1e72Sjeremylt @param r Address of the variable where the newly created 163b11c1e72Sjeremylt CeedElemRestriction will be stored 164d7b241e6Sjeremylt 165b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 166*dfdf5a53Sjeremylt 167*dfdf5a53Sjeremylt @ref Advanced 168b11c1e72Sjeremylt **/ 169d7b241e6Sjeremylt int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt nelem, CeedInt elemsize, 170d7b241e6Sjeremylt CeedInt blksize, CeedInt ndof, CeedInt ncomp, 171d7b241e6Sjeremylt CeedMemType mtype, CeedCopyMode cmode, 172d7b241e6Sjeremylt const CeedInt *indices, CeedElemRestriction *r) { 173d7b241e6Sjeremylt int ierr; 174d7b241e6Sjeremylt CeedInt *blkindices; 175d7b241e6Sjeremylt CeedInt nblk = (nelem / blksize) + !!(nelem % blksize); 176d7b241e6Sjeremylt 177d7b241e6Sjeremylt if (!ceed->ElemRestrictionCreateBlocked) 178d7b241e6Sjeremylt return CeedError(ceed, 1, 179d7b241e6Sjeremylt "Backend does not support ElemRestrictionCreateBlocked"); 180d7b241e6Sjeremylt if (mtype != CEED_MEM_HOST) 181d7b241e6Sjeremylt return CeedError(ceed, 1, "Only MemType = HOST supported"); 182d7b241e6Sjeremylt 183d7b241e6Sjeremylt ierr = CeedCalloc(1, r); CeedChk(ierr); 184d7b241e6Sjeremylt 185d7b241e6Sjeremylt if (indices) { 186d7b241e6Sjeremylt ierr = CeedCalloc(nblk*blksize*elemsize, &blkindices); 187*dfdf5a53Sjeremylt ierr = CeedPermutePadIndices(indices, blkindices, nblk, nelem, blksize, elemsize); 188*dfdf5a53Sjeremylt CeedChk(ierr); 189d7b241e6Sjeremylt } else { 190d7b241e6Sjeremylt blkindices = NULL; 191d7b241e6Sjeremylt } 192d7b241e6Sjeremylt 193d7b241e6Sjeremylt (*r)->ceed = ceed; 194d7b241e6Sjeremylt ceed->refcount++; 195d7b241e6Sjeremylt (*r)->refcount = 1; 196d7b241e6Sjeremylt (*r)->nelem = nelem; 197d7b241e6Sjeremylt (*r)->elemsize = elemsize; 198d7b241e6Sjeremylt (*r)->ndof = ndof; 199d7b241e6Sjeremylt (*r)->ncomp = ncomp; 200d7b241e6Sjeremylt (*r)->nblk = nblk; 201d7b241e6Sjeremylt (*r)->blksize = blksize; 202d7b241e6Sjeremylt ierr = ceed->ElemRestrictionCreateBlocked(*r, CEED_MEM_HOST, CEED_OWN_POINTER, 203d7b241e6Sjeremylt (const CeedInt *) blkindices); 204d7b241e6Sjeremylt CeedChk(ierr); 205d7b241e6Sjeremylt 206d7b241e6Sjeremylt if (cmode == CEED_OWN_POINTER) 207d7b241e6Sjeremylt ierr = CeedFree(&indices); CeedChk(ierr); 208d7b241e6Sjeremylt 209d7b241e6Sjeremylt return 0; 210d7b241e6Sjeremylt } 211d7b241e6Sjeremylt 212b11c1e72Sjeremylt /** 213b11c1e72Sjeremylt @brief Create CeedVectors associated with a CeedElemRestriction 214b11c1e72Sjeremylt 215b11c1e72Sjeremylt @param r CeedElemRestriction 216b11c1e72Sjeremylt @param lvec The address of the L-vector to be created, or NULL 217b11c1e72Sjeremylt @param evec The address of the E-vector to be created, or NULL 218b11c1e72Sjeremylt 219b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 220*dfdf5a53Sjeremylt 221*dfdf5a53Sjeremylt @ref Advanced 222b11c1e72Sjeremylt **/ 223d7b241e6Sjeremylt int CeedElemRestrictionCreateVector(CeedElemRestriction r, CeedVector *lvec, 224d7b241e6Sjeremylt CeedVector *evec) { 225d7b241e6Sjeremylt int ierr; 226d7b241e6Sjeremylt CeedInt n, m; 227d7b241e6Sjeremylt m = r->ndof * r->ncomp; 228d7b241e6Sjeremylt n = r->nblk * r->blksize * r->elemsize * r->ncomp; 229d7b241e6Sjeremylt if (lvec) { 230d7b241e6Sjeremylt ierr = CeedVectorCreate(r->ceed, m, lvec); CeedChk(ierr); 231d7b241e6Sjeremylt } 232d7b241e6Sjeremylt if (evec) { 233d7b241e6Sjeremylt ierr = CeedVectorCreate(r->ceed, n, evec); CeedChk(ierr); 234d7b241e6Sjeremylt } 235d7b241e6Sjeremylt return 0; 236d7b241e6Sjeremylt } 237d7b241e6Sjeremylt 238d7b241e6Sjeremylt /** 239b11c1e72Sjeremylt @brief Restrict an L-vector to an E-vector or apply transpose 240d7b241e6Sjeremylt 241b11c1e72Sjeremylt @param r CeedElemRestriction 242d7b241e6Sjeremylt @param tmode Apply restriction or transpose 243d7b241e6Sjeremylt @param lmode Ordering of the ncomp components 244d7b241e6Sjeremylt @param u Input vector (of size @a ndof when tmode=CEED_NOTRANSPOSE) 245d7b241e6Sjeremylt @param v Output vector (of size @a nelem * @a elemsize when tmode=CEED_NOTRANSPOSE) 246d7b241e6Sjeremylt @param request Request or CEED_REQUEST_IMMEDIATE 247b11c1e72Sjeremylt 248b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 249*dfdf5a53Sjeremylt 250*dfdf5a53Sjeremylt @ref Advanced 251b11c1e72Sjeremylt **/ 252d7b241e6Sjeremylt int CeedElemRestrictionApply(CeedElemRestriction r, CeedTransposeMode tmode, 253d7b241e6Sjeremylt CeedTransposeMode lmode, 254d7b241e6Sjeremylt CeedVector u, CeedVector v, CeedRequest *request) { 255d7b241e6Sjeremylt CeedInt m,n; 256d7b241e6Sjeremylt int ierr; 257d7b241e6Sjeremylt 258d7b241e6Sjeremylt if (tmode == CEED_NOTRANSPOSE) { 259d7b241e6Sjeremylt m = r->nblk * r->blksize * r->elemsize * r->ncomp; 260d7b241e6Sjeremylt n = r->ndof * r->ncomp; 261d7b241e6Sjeremylt } else { 262d7b241e6Sjeremylt m = r->ndof * r->ncomp; 263d7b241e6Sjeremylt n = r->nblk * r->blksize * r->elemsize * r->ncomp; 264d7b241e6Sjeremylt } 265d7b241e6Sjeremylt if (n != u->length) 266d7b241e6Sjeremylt return CeedError(r->ceed, 2, 267d7b241e6Sjeremylt "Input vector size %d not compatible with element restriction (%d, %d)", 268d7b241e6Sjeremylt u->length, m, n); 269d7b241e6Sjeremylt if (m != v->length) 270d7b241e6Sjeremylt return CeedError(r->ceed, 2, 271d7b241e6Sjeremylt "Output vector size %d not compatible with element restriction (%d, %d)", 272d7b241e6Sjeremylt v->length, m, n); 273d7b241e6Sjeremylt ierr = r->Apply(r, tmode, lmode, u, v, request); CeedChk(ierr); 274d7b241e6Sjeremylt 275d7b241e6Sjeremylt return 0; 276d7b241e6Sjeremylt } 277d7b241e6Sjeremylt 278d7b241e6Sjeremylt /** 279b11c1e72Sjeremylt @brief Get the total number of elements in the range of a CeedElemRestriction 280d7b241e6Sjeremylt 281b11c1e72Sjeremylt @param r CeedElemRestriction 282b11c1e72Sjeremylt @param[out] numelements Number of elements 283b11c1e72Sjeremylt 284b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 285*dfdf5a53Sjeremylt 286*dfdf5a53Sjeremylt @ref Utility 287b11c1e72Sjeremylt **/ 288d7b241e6Sjeremylt int CeedElemRestrictionGetNumElements(CeedElemRestriction r, 289d7b241e6Sjeremylt CeedInt *numelements) { 290d7b241e6Sjeremylt *numelements = r->nelem; 291d7b241e6Sjeremylt return 0; 292d7b241e6Sjeremylt } 293d7b241e6Sjeremylt 294d7b241e6Sjeremylt /** 295b11c1e72Sjeremylt @brief Destroy a CeedElemRestriction 296b11c1e72Sjeremylt 297b11c1e72Sjeremylt @param r CeedElemRestriction to destroy 298b11c1e72Sjeremylt 299b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 300*dfdf5a53Sjeremylt 301*dfdf5a53Sjeremylt @ref Basic 302b11c1e72Sjeremylt **/ 303d7b241e6Sjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *r) { 304d7b241e6Sjeremylt int ierr; 305d7b241e6Sjeremylt 306d7b241e6Sjeremylt if (!*r || --(*r)->refcount > 0) return 0; 307d7b241e6Sjeremylt if ((*r)->Destroy) { 308d7b241e6Sjeremylt ierr = (*r)->Destroy(*r); CeedChk(ierr); 309d7b241e6Sjeremylt } 310d7b241e6Sjeremylt ierr = CeedDestroy(&(*r)->ceed); CeedChk(ierr); 311d7b241e6Sjeremylt ierr = CeedFree(r); CeedChk(ierr); 312d7b241e6Sjeremylt return 0; 313d7b241e6Sjeremylt } 314d7b241e6Sjeremylt 315d7b241e6Sjeremylt /// @} 316