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