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