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