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