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