xref: /libCEED/interface/ceed-elemrestriction.c (revision d7b241e67f6e33d9b297db3da3be4f167f32bbee)
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