xref: /libCEED/interface/ceed-elemrestriction.c (revision 2774d5cba221882c6b4100a2009c80f26d4c6f5c)
1 // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3 // reserved. See files LICENSE and NOTICE for details.
4 //
5 // This file is part of CEED, a collection of benchmarks, miniapps, software
6 // libraries and APIs for efficient high-order finite element and spectral
7 // element discretizations for exascale applications. For more information and
8 // source code availability see http://github.com/ceed.
9 //
10 // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11 // a collaborative effort of two U.S. Department of Energy organizations (Office
12 // of Science and the National Nuclear Security Administration) responsible for
13 // the planning and preparation of a capable exascale ecosystem, including
14 // software, applications, hardware, advanced system engineering and early
15 // testbed platforms, in support of the nation's exascale computing imperative.
16 
17 #include <ceed-impl.h>
18 #include <ceed-backend.h>
19 
20 /// @file
21 /// Implementation of public CeedElemRestriction interfaces
22 ///
23 /// @addtogroup CeedElemRestriction
24 /// @{
25 
26 /**
27   @brief Create a CeedElemRestriction
28 
29   @param ceed       A Ceed object where the CeedElemRestriction will be created
30   @param nelem      Number of elements described in the @a indices array
31   @param elemsize   Size (number of "nodes") per element
32   @param ndof       The total size of the input CeedVector to which the
33                       restriction will be applied. This size may include data
34                       used by other CeedElemRestriction objects describing
35                       different types of elements.
36   @param ncomp      Number of field components per interpolation node
37   @param mtype      Memory type of the @a indices array, see CeedMemType
38   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
39   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the ordered list
40                       of the indices (into the input CeedVector) for the unknowns
41                       corresponding to element i, where 0 <= i < @a nelements.
42                       All indices must be in the range [0, @a ndof).
43   @param[out] rstr  Address of the variable where the newly created
44                       CeedElemRestriction will be stored
45 
46   @return An error code: 0 - success, otherwise - failure
47 
48   @ref Basic
49 **/
50 int CeedElemRestrictionCreate(Ceed ceed, CeedInt nelem, CeedInt elemsize,
51                               CeedInt ndof, CeedInt ncomp, CeedMemType mtype,
52                               CeedCopyMode cmode, const CeedInt *indices,
53                               CeedElemRestriction *rstr) {
54   int ierr;
55 
56   if (!ceed->ElemRestrictionCreate) {
57     Ceed delegate;
58     ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr);
59 
60     if (!delegate)
61       return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
62 
63     ierr = CeedElemRestrictionCreate(delegate, nelem, elemsize,
64                                      ndof, ncomp, mtype, cmode,
65                                      indices, rstr); CeedChk(ierr);
66     return 0;
67   }
68 
69   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
70   (*rstr)->ceed = ceed;
71   ceed->refcount++;
72   (*rstr)->refcount = 1;
73   (*rstr)->nelem = nelem;
74   (*rstr)->elemsize = elemsize;
75   (*rstr)->ndof = ndof;
76   (*rstr)->ncomp = ncomp;
77   (*rstr)->nblk = nelem;
78   (*rstr)->blksize = 1;
79   ierr = ceed->ElemRestrictionCreate(mtype, cmode, indices, *rstr); CeedChk(ierr);
80   return 0;
81 }
82 
83 /**
84   @brief Create an identity CeedElemRestriction
85 
86   @param ceed       A Ceed object where the CeedElemRestriction will be created
87   @param nelem      Number of elements described in the @a indices array
88   @param elemsize   Size (number of "nodes") per element
89   @param ndof       The total size of the input CeedVector to which the
90                       restriction will be applied. This size may include data
91                       used by other CeedElemRestriction objects describing
92                       different types of elements
93   @param ncomp      Number of field components per interpolation node
94   @param rstr       Address of the variable where the newly created
95                       CeedElemRestriction will be stored
96 
97   @return An error code: 0 - success, otherwise - failure
98 
99   @ref Basic
100 **/
101 int CeedElemRestrictionCreateIdentity(Ceed ceed, CeedInt nelem,
102                                       CeedInt elemsize,
103                                       CeedInt ndof, CeedInt ncomp, CeedElemRestriction *rstr) {
104   int ierr;
105 
106   if (!ceed->ElemRestrictionCreate) {
107     Ceed delegate;
108     ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr);
109 
110     if (!delegate)
111       return CeedError(ceed, 1,
112                        "Backend does not support ElemRestrictionCreate");
113 
114     ierr = CeedElemRestrictionCreateIdentity(delegate, nelem, elemsize,
115            ndof, ncomp, rstr); CeedChk(ierr);
116     return 0;
117   }
118 
119   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
120   (*rstr)->ceed = ceed;
121   ceed->refcount++;
122   (*rstr)->refcount = 1;
123   (*rstr)->nelem = nelem;
124   (*rstr)->elemsize = elemsize;
125   (*rstr)->ndof = ndof;
126   (*rstr)->ncomp = ncomp;
127   (*rstr)->nblk = nelem;
128   (*rstr)->blksize = 1;
129   ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL,
130                                      *rstr);
131   CeedChk(ierr);
132   return 0;
133 }
134 
135 /**
136   @brief Permute and pad indices for a blocked restriction
137 
138   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the ordered list
139                       of the indices (into the input CeedVector) for the unknowns
140                       corresponding to element i, where 0 <= i < @a nelements.
141                       All indices must be in the range [0, @a ndof).
142   @param blkindices Array of permuted and padded indices of
143                       shape [@a nblk, @a elemsize, @a blksize].
144   @param nblk       Number of blocks
145   @param nelem      Number of elements
146   @param blksize    Number of elements in a block
147   @param elemsize   Size of each element
148 
149   @return An error code: 0 - success, otherwise - failure
150 
151   @ref Utility
152 **/
153 int CeedPermutePadIndices(const CeedInt *indices, CeedInt *blkindices,
154                           CeedInt nblk, CeedInt nelem,
155                           CeedInt blksize, CeedInt elemsize) {
156   for (CeedInt e = 0; e < nblk*blksize; e+=blksize)
157     for (int j = 0; j < blksize; j++)
158       for (int k = 0; k < elemsize; k++)
159         blkindices[e*elemsize + k*blksize + j]
160           = indices[CeedIntMin(e+j,nelem-1)*elemsize + k];
161   return 0;
162 }
163 
164 /**
165   @brief Create a blocked CeedElemRestriction, typically only called by backends
166 
167   @param ceed       A Ceed object where the CeedElemRestriction will be created.
168   @param nelem      Number of elements described in the @a indices array.
169   @param elemsize   Size (number of unknowns) per element
170   @param blksize    Number of elements in a block
171   @param ndof       The total size of the input CeedVector to which the
172                       restriction will be applied. This size may include data
173                       used by other CeedElemRestriction objects describing
174                       different types of elements.
175   @param ncomp      Number of components stored at each node
176   @param mtype      Memory type of the @a indices array, see CeedMemType
177   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
178   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the ordered list
179                       of the indices (into the input CeedVector) for the unknowns
180                       corresponding to element i, where 0 <= i < @a nelements.
181                       All indices must be in the range [0, @a ndof). The
182                       backend will permute and pad this array to the desired
183                       ordering for the blocksize, which is typically given by the
184                       backend. The default reordering is to interlace elements.
185   @param rstr       Address of the variable where the newly created
186                       CeedElemRestriction will be stored
187 
188   @return An error code: 0 - success, otherwise - failure
189 
190   @ref Advanced
191  **/
192 int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt nelem, CeedInt elemsize,
193                                      CeedInt blksize, CeedInt ndof, CeedInt ncomp,
194                                      CeedMemType mtype, CeedCopyMode cmode,
195                                      const CeedInt *indices,
196                                      CeedElemRestriction *rstr) {
197   int ierr;
198   CeedInt *blkindices;
199   CeedInt nblk = (nelem / blksize) + !!(nelem % blksize);
200 
201   if (!ceed->ElemRestrictionCreateBlocked) {
202     Ceed delegate;
203     ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr);
204 
205     if (!delegate)
206       return CeedError(ceed, 1,
207                        "Backend does not support ElemRestrictionCreateBlocked");
208 
209     ierr = CeedElemRestrictionCreateBlocked(delegate, nelem, elemsize,
210                                             blksize, ndof, ncomp, mtype, cmode,
211                                             indices, rstr); CeedChk(ierr);
212     return 0;
213   }
214 
215   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
216 
217   if (indices) {
218     ierr = CeedCalloc(nblk*blksize*elemsize, &blkindices); CeedChk(ierr);
219     ierr = CeedPermutePadIndices(indices, blkindices, nblk, nelem, blksize,
220                                  elemsize);
221     CeedChk(ierr);
222   } else {
223     blkindices = NULL;
224   }
225 
226   (*rstr)->ceed = ceed;
227   ceed->refcount++;
228   (*rstr)->refcount = 1;
229   (*rstr)->nelem = nelem;
230   (*rstr)->elemsize = elemsize;
231   (*rstr)->ndof = ndof;
232   (*rstr)->ncomp = ncomp;
233   (*rstr)->nblk = nblk;
234   (*rstr)->blksize = blksize;
235   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
236          (const CeedInt *) blkindices, *rstr);
237   CeedChk(ierr);
238 
239   if (cmode == CEED_OWN_POINTER)
240     ierr = CeedFree(&indices); CeedChk(ierr);
241 
242   return 0;
243 }
244 
245 /**
246   @brief Create CeedVectors associated with a CeedElemRestriction
247 
248   @param rstr  CeedElemRestriction
249   @param lvec  The address of the L-vector to be created, or NULL
250   @param evec  The address of the E-vector to be created, or NULL
251 
252   @return An error code: 0 - success, otherwise - failure
253 
254   @ref Advanced
255 **/
256 int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *lvec,
257                                     CeedVector *evec) {
258   int ierr;
259   CeedInt n, m;
260   m = rstr->ndof * rstr->ncomp;
261   n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
262   if (lvec) {
263     ierr = CeedVectorCreate(rstr->ceed, m, lvec); CeedChk(ierr);
264   }
265   if (evec) {
266     ierr = CeedVectorCreate(rstr->ceed, n, evec); CeedChk(ierr);
267   }
268   return 0;
269 }
270 
271 /**
272   @brief Restrict an L-vector to an E-vector or apply transpose
273 
274   @param rstr    CeedElemRestriction
275   @param tmode   Apply restriction or transpose
276   @param lmode   Ordering of the ncomp components
277   @param u       Input vector (of size @a ndof when tmode=CEED_NOTRANSPOSE)
278   @param v       Output vector (of size @a nelem * @a elemsize when tmode=CEED_NOTRANSPOSE)
279   @param request Request or CEED_REQUEST_IMMEDIATE
280 
281   @return An error code: 0 - success, otherwise - failure
282 
283   @ref Advanced
284 **/
285 int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode tmode,
286                              CeedTransposeMode lmode,
287                              CeedVector u, CeedVector v, CeedRequest *request) {
288   CeedInt m,n;
289   int ierr;
290 
291   if (tmode == CEED_NOTRANSPOSE) {
292     m = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
293     n = rstr->ndof * rstr->ncomp;
294   } else {
295     m = rstr->ndof * rstr->ncomp;
296     n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
297   }
298   if (n != u->length)
299     return CeedError(rstr->ceed, 2,
300                      "Input vector size %d not compatible with element restriction (%d, %d)",
301                      u->length, m, n);
302   if (m != v->length)
303     return CeedError(rstr->ceed, 2,
304                      "Output vector size %d not compatible with element restriction (%d, %d)",
305                      v->length, m, n);
306   ierr = rstr->Apply(rstr, tmode, lmode, u, v, request); CeedChk(ierr);
307 
308   return 0;
309 }
310 
311 /**
312   @brief Get the Ceed associated with a CeedElemRestriction
313 
314   @param rstr             CeedElemRestriction
315   @param[out] ceed        Variable to store Ceed
316 
317   @return An error code: 0 - success, otherwise - failure
318 
319   @ref Advanced
320 **/
321 int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
322   *ceed = rstr->ceed;
323   return 0;
324 }
325 
326 /**
327   @brief Get the total number of elements in the range of a CeedElemRestriction
328 
329   @param rstr             CeedElemRestriction
330   @param[out] numelements Variable to store number of elements
331 
332   @return An error code: 0 - success, otherwise - failure
333 
334   @ref Advanced
335 **/
336 int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
337                                       CeedInt *numelem) {
338   *numelem = rstr->nelem;
339   return 0;
340 }
341 
342 /**
343   @brief Get the size of elements in the CeedElemRestriction
344 
345   @param rstr             CeedElemRestriction
346   @param[out] elemsize    Variable to store size of elements
347 
348   @return An error code: 0 - success, otherwise - failure
349 
350   @ref Advanced
351 **/
352 int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
353                                       CeedInt *elemsize) {
354   *elemsize = rstr->elemsize;
355   return 0;
356 }
357 
358 /**
359   @brief Get the number of degrees of freedom in the range of a
360          CeedElemRestriction
361 
362   @param rstr             CeedElemRestriction
363   @param[out] numdof      Variable to store number of DoFs
364 
365   @return An error code: 0 - success, otherwise - failure
366 
367   @ref Advanced
368 **/
369 int CeedElemRestrictionGetNumDoF(CeedElemRestriction rstr,
370                                  CeedInt *numdof) {
371   *numdof = rstr->ndof;
372   return 0;
373 }
374 
375 /**
376   @brief Get the number of components in the elements of a
377          CeedElemRestriction
378 
379   @param rstr             CeedElemRestriction
380   @param[out] numcomp     Variable to store number of components
381 
382   @return An error code: 0 - success, otherwise - failure
383 
384   @ref Advanced
385 **/
386 int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
387                                         CeedInt *numcomp) {
388   *numcomp = rstr->ncomp;
389   return 0;
390 }
391 
392 /**
393   @brief Get the number of blocks in a CeedElemRestriction
394 
395   @param rstr             CeedElemRestriction
396   @param[out] numblock    Variable to store number of blocks
397 
398   @return An error code: 0 - success, otherwise - failure
399 
400   @ref Advanced
401 **/
402 int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
403                                     CeedInt *numblock) {
404   *numblock = rstr->nblk;
405   return 0;
406 }
407 
408 /**
409   @brief Get the size of blocks in the CeedElemRestriction
410 
411   @param r                CeedElemRestriction
412   @param[out] blksize     Variable to store size of blocks
413 
414   @return An error code: 0 - success, otherwise - failure
415 
416   @ref Advanced
417 **/
418 int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
419                                     CeedInt *blksize) {
420   *blksize = rstr->blksize;
421   return 0;
422 }
423 
424 /**
425   @brief Get the backend data of a CeedElemRestriction
426 
427   @param r                CeedElemRestriction
428   @param[out] data        Variable to store data
429 
430   @return An error code: 0 - success, otherwise - failure
431 
432   @ref Advanced
433 **/
434 int CeedElemRestrictionGetData(CeedElemRestriction rstr,
435                                void* *data) {
436   *data = rstr->data;
437   return 0;
438 }
439 
440 /**
441   @brief Set the backend data of a CeedElemRestriction
442 
443   @param[out] r           CeedElemRestriction
444   @param data             Data to set
445 
446   @return An error code: 0 - success, otherwise - failure
447 
448   @ref Advanced
449 **/
450 int CeedElemRestrictionSetData(CeedElemRestriction rstr,
451                                void* *data) {
452   rstr->data = *data;
453   return 0;
454 }
455 
456 /**
457   @brief Destroy a CeedElemRestriction
458 
459   @param rstr CeedElemRestriction to destroy
460 
461   @return An error code: 0 - success, otherwise - failure
462 
463   @ref Basic
464 **/
465 int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
466   int ierr;
467 
468   if (!*rstr || --(*rstr)->refcount > 0) return 0;
469   if ((*rstr)->Destroy) {
470     ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr);
471   }
472   ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr);
473   ierr = CeedFree(rstr); CeedChk(ierr);
474   return 0;
475 }
476 
477 /// @}
478