xref: /libCEED/interface/ceed-elemrestriction.c (revision 1048f70dd04f571b453a801f25f7ee1030615af0)
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 = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
59     CeedChk(ierr);
60 
61     if (!delegate)
62       return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
63 
64     ierr = CeedElemRestrictionCreate(delegate, nelem, elemsize,
65                                      ndof, ncomp, mtype, cmode,
66                                      indices, rstr); CeedChk(ierr);
67     return 0;
68   }
69 
70   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
71   (*rstr)->ceed = ceed;
72   ceed->refcount++;
73   (*rstr)->refcount = 1;
74   (*rstr)->nelem = nelem;
75   (*rstr)->elemsize = elemsize;
76   (*rstr)->ndof = ndof;
77   (*rstr)->ncomp = ncomp;
78   (*rstr)->nblk = nelem;
79   (*rstr)->blksize = 1;
80   ierr = ceed->ElemRestrictionCreate(mtype, cmode, indices, *rstr); CeedChk(ierr);
81   return 0;
82 }
83 
84 /**
85   @brief Create an identity CeedElemRestriction
86 
87   @param ceed       A Ceed object where the CeedElemRestriction will be created
88   @param nelem      Number of elements described in the @a indices array
89   @param elemsize   Size (number of "nodes") per element
90   @param ndof       The total size of the input CeedVector to which the
91                       restriction will be applied. This size may include data
92                       used by other CeedElemRestriction objects describing
93                       different types of elements
94   @param ncomp      Number of field components per interpolation node
95   @param rstr       Address of the variable where the newly created
96                       CeedElemRestriction will be stored
97 
98   @return An error code: 0 - success, otherwise - failure
99 
100   @ref Basic
101 **/
102 int CeedElemRestrictionCreateIdentity(Ceed ceed, CeedInt nelem,
103                                       CeedInt elemsize,
104                                       CeedInt ndof, CeedInt ncomp, CeedElemRestriction *rstr) {
105   int ierr;
106 
107   if (!ceed->ElemRestrictionCreate) {
108     Ceed delegate;
109     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
110     CeedChk(ierr);
111 
112     if (!delegate)
113       return CeedError(ceed, 1,
114                        "Backend does not support ElemRestrictionCreate");
115 
116     ierr = CeedElemRestrictionCreateIdentity(delegate, nelem, elemsize,
117            ndof, ncomp, rstr); CeedChk(ierr);
118     return 0;
119   }
120 
121   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
122   (*rstr)->ceed = ceed;
123   ceed->refcount++;
124   (*rstr)->refcount = 1;
125   (*rstr)->nelem = nelem;
126   (*rstr)->elemsize = elemsize;
127   (*rstr)->ndof = ndof;
128   (*rstr)->ncomp = ncomp;
129   (*rstr)->nblk = nelem;
130   (*rstr)->blksize = 1;
131   ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL,
132                                      *rstr);
133   CeedChk(ierr);
134   return 0;
135 }
136 
137 /**
138   @brief Permute and pad indices for a blocked restriction
139 
140   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the ordered list
141                       of the indices (into the input CeedVector) for the unknowns
142                       corresponding to element i, where 0 <= i < @a nelements.
143                       All indices must be in the range [0, @a ndof).
144   @param blkindices Array of permuted and padded indices of
145                       shape [@a nblk, @a elemsize, @a blksize].
146   @param nblk       Number of blocks
147   @param nelem      Number of elements
148   @param blksize    Number of elements in a block
149   @param elemsize   Size of each element
150 
151   @return An error code: 0 - success, otherwise - failure
152 
153   @ref Utility
154 **/
155 int CeedPermutePadIndices(const CeedInt *indices, CeedInt *blkindices,
156                           CeedInt nblk, CeedInt nelem,
157                           CeedInt blksize, CeedInt elemsize) {
158   for (CeedInt e = 0; e < nblk*blksize; e+=blksize)
159     for (int j = 0; j < blksize; j++)
160       for (int k = 0; k < elemsize; k++)
161         blkindices[e*elemsize + k*blksize + j]
162           = indices[CeedIntMin(e+j,nelem-1)*elemsize + k];
163   return 0;
164 }
165 
166 /**
167   @brief Create a blocked CeedElemRestriction, typically only called by backends
168 
169   @param ceed       A Ceed object where the CeedElemRestriction will be created.
170   @param nelem      Number of elements described in the @a indices array.
171   @param elemsize   Size (number of unknowns) per element
172   @param blksize    Number of elements in a block
173   @param ndof       The total size of the input CeedVector to which the
174                       restriction will be applied. This size may include data
175                       used by other CeedElemRestriction objects describing
176                       different types of elements.
177   @param ncomp      Number of components stored at each node
178   @param mtype      Memory type of the @a indices array, see CeedMemType
179   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
180   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the ordered list
181                       of the indices (into the input CeedVector) for the unknowns
182                       corresponding to element i, where 0 <= i < @a nelements.
183                       All indices must be in the range [0, @a ndof). The
184                       backend will permute and pad this array to the desired
185                       ordering for the blocksize, which is typically given by the
186                       backend. The default reordering is to interlace elements.
187   @param rstr       Address of the variable where the newly created
188                       CeedElemRestriction will be stored
189 
190   @return An error code: 0 - success, otherwise - failure
191 
192   @ref Advanced
193  **/
194 int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt nelem, CeedInt elemsize,
195                                      CeedInt blksize, CeedInt ndof, CeedInt ncomp,
196                                      CeedMemType mtype, CeedCopyMode cmode,
197                                      const CeedInt *indices,
198                                      CeedElemRestriction *rstr) {
199   int ierr;
200   CeedInt *blkindices;
201   CeedInt nblk = (nelem / blksize) + !!(nelem % blksize);
202 
203   if (!ceed->ElemRestrictionCreateBlocked) {
204     Ceed delegate;
205     ierr = CeedGetObjectDelegate(ceed, &delegate, "ElemRestriction");
206     CeedChk(ierr);
207 
208     if (!delegate)
209       return CeedError(ceed, 1,
210                        "Backend does not support ElemRestrictionCreateBlocked");
211 
212     ierr = CeedElemRestrictionCreateBlocked(delegate, nelem, elemsize,
213                                             blksize, ndof, ncomp, mtype, cmode,
214                                             indices, rstr); CeedChk(ierr);
215     return 0;
216   }
217 
218   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
219 
220   if (indices) {
221     ierr = CeedCalloc(nblk*blksize*elemsize, &blkindices); CeedChk(ierr);
222     ierr = CeedPermutePadIndices(indices, blkindices, nblk, nelem, blksize,
223                                  elemsize);
224     CeedChk(ierr);
225   } else {
226     blkindices = NULL;
227   }
228 
229   (*rstr)->ceed = ceed;
230   ceed->refcount++;
231   (*rstr)->refcount = 1;
232   (*rstr)->nelem = nelem;
233   (*rstr)->elemsize = elemsize;
234   (*rstr)->ndof = ndof;
235   (*rstr)->ncomp = ncomp;
236   (*rstr)->nblk = nblk;
237   (*rstr)->blksize = blksize;
238   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
239          (const CeedInt *) blkindices, *rstr);
240   CeedChk(ierr);
241 
242   if (cmode == CEED_OWN_POINTER)
243     ierr = CeedFree(&indices); CeedChk(ierr);
244 
245   return 0;
246 }
247 
248 /**
249   @brief Create CeedVectors associated with a CeedElemRestriction
250 
251   @param rstr  CeedElemRestriction
252   @param lvec  The address of the L-vector to be created, or NULL
253   @param evec  The address of the E-vector to be created, or NULL
254 
255   @return An error code: 0 - success, otherwise - failure
256 
257   @ref Advanced
258 **/
259 int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *lvec,
260                                     CeedVector *evec) {
261   int ierr;
262   CeedInt n, m;
263   m = rstr->ndof * rstr->ncomp;
264   n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
265   if (lvec) {
266     ierr = CeedVectorCreate(rstr->ceed, m, lvec); CeedChk(ierr);
267   }
268   if (evec) {
269     ierr = CeedVectorCreate(rstr->ceed, n, evec); CeedChk(ierr);
270   }
271   return 0;
272 }
273 
274 /**
275   @brief Restrict an L-vector to an E-vector or apply transpose
276 
277   @param rstr    CeedElemRestriction
278   @param tmode   Apply restriction or transpose
279   @param lmode   Ordering of the ncomp components
280   @param u       Input vector (of size @a ndof when tmode=CEED_NOTRANSPOSE)
281   @param v       Output vector (of size @a nelem * @a elemsize when tmode=CEED_NOTRANSPOSE)
282   @param request Request or CEED_REQUEST_IMMEDIATE
283 
284   @return An error code: 0 - success, otherwise - failure
285 
286   @ref Advanced
287 **/
288 int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode tmode,
289                              CeedTransposeMode lmode,
290                              CeedVector u, CeedVector v, CeedRequest *request) {
291   CeedInt m,n;
292   int ierr;
293 
294   if (tmode == CEED_NOTRANSPOSE) {
295     m = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
296     n = rstr->ndof * rstr->ncomp;
297   } else {
298     m = rstr->ndof * rstr->ncomp;
299     n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
300   }
301   if (n != u->length)
302     return CeedError(rstr->ceed, 2,
303                      "Input vector size %d not compatible with element restriction (%d, %d)",
304                      u->length, m, n);
305   if (m != v->length)
306     return CeedError(rstr->ceed, 2,
307                      "Output vector size %d not compatible with element restriction (%d, %d)",
308                      v->length, m, n);
309   ierr = rstr->Apply(rstr, tmode, lmode, u, v, request); CeedChk(ierr);
310 
311   return 0;
312 }
313 
314 /**
315   @brief Restrict an L-vector to a block of an E-vector or apply transpose
316 
317   @param rstr    CeedElemRestriction
318   @param block   Block number to restrict to/from, i.e. block=0 will handle
319                  elements [0 : blksize] and block=3 will handle elements
320                  [3*blksize : 4*blksize]
321   @param tmode   Apply restriction or transpose
322   @param lmode   Ordering of the ncomp components
323   @param u       Input vector (of size @a ndof when tmode=CEED_NOTRANSPOSE)
324   @param v       Output vector (of size @a nelem * @a elemsize when tmode=CEED_NOTRANSPOSE)
325   @param request Request or CEED_REQUEST_IMMEDIATE
326 
327   @return An error code: 0 - success, otherwise - failure
328 
329   @ref Advanced
330 **/
331 int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block,
332                                   CeedTransposeMode tmode,
333                                   CeedTransposeMode lmode,
334                                   CeedVector u, CeedVector v,
335                                   CeedRequest *request) {
336   CeedInt m,n;
337   int ierr;
338 
339   if (tmode == CEED_NOTRANSPOSE) {
340     m = rstr->blksize * rstr->elemsize * rstr->ncomp;
341     n = rstr->ndof * rstr->ncomp;
342   } else {
343     m = rstr->ndof * rstr->ncomp;
344     n = rstr->blksize * rstr->elemsize * rstr->ncomp;
345   }
346   if (n != u->length)
347     return CeedError(rstr->ceed, 2,
348                      "Input vector size %d not compatible with element restriction (%d, %d)",
349                      u->length, m, n);
350   if (m != v->length)
351     return CeedError(rstr->ceed, 2,
352                      "Output vector size %d not compatible with element restriction (%d, %d)",
353                      v->length, m, n);
354   if (rstr->blksize*block > rstr->nelem)
355     return CeedError(rstr->ceed, 2,
356                      "Cannot retrieve block %d, element %d > total elements %d",
357                      block, rstr->blksize*block, rstr->nelem);
358   ierr = rstr->ApplyBlock(rstr, block, tmode, lmode, u, v, request);
359   CeedChk(ierr);
360 
361   return 0;
362 }
363 
364 /**
365   @brief Get the Ceed associated with a CeedElemRestriction
366 
367   @param rstr             CeedElemRestriction
368   @param[out] ceed        Variable to store Ceed
369 
370   @return An error code: 0 - success, otherwise - failure
371 
372   @ref Advanced
373 **/
374 int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
375   *ceed = rstr->ceed;
376   return 0;
377 }
378 
379 /**
380   @brief Get the total number of elements in the range of a CeedElemRestriction
381 
382   @param rstr             CeedElemRestriction
383   @param[out] numelements Variable to store number of elements
384 
385   @return An error code: 0 - success, otherwise - failure
386 
387   @ref Advanced
388 **/
389 int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
390                                       CeedInt *numelem) {
391   *numelem = rstr->nelem;
392   return 0;
393 }
394 
395 /**
396   @brief Get the size of elements in the CeedElemRestriction
397 
398   @param rstr             CeedElemRestriction
399   @param[out] elemsize    Variable to store size of elements
400 
401   @return An error code: 0 - success, otherwise - failure
402 
403   @ref Advanced
404 **/
405 int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
406                                       CeedInt *elemsize) {
407   *elemsize = rstr->elemsize;
408   return 0;
409 }
410 
411 /**
412   @brief Get the number of degrees of freedom in the range of a
413          CeedElemRestriction
414 
415   @param rstr             CeedElemRestriction
416   @param[out] numdof      Variable to store number of DoFs
417 
418   @return An error code: 0 - success, otherwise - failure
419 
420   @ref Advanced
421 **/
422 int CeedElemRestrictionGetNumDoF(CeedElemRestriction rstr,
423                                  CeedInt *numdof) {
424   *numdof = rstr->ndof;
425   return 0;
426 }
427 
428 /**
429   @brief Get the number of components in the elements of a
430          CeedElemRestriction
431 
432   @param rstr             CeedElemRestriction
433   @param[out] numcomp     Variable to store number of components
434 
435   @return An error code: 0 - success, otherwise - failure
436 
437   @ref Advanced
438 **/
439 int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
440                                         CeedInt *numcomp) {
441   *numcomp = rstr->ncomp;
442   return 0;
443 }
444 
445 /**
446   @brief Get the number of blocks in a CeedElemRestriction
447 
448   @param rstr             CeedElemRestriction
449   @param[out] numblock    Variable to store number of blocks
450 
451   @return An error code: 0 - success, otherwise - failure
452 
453   @ref Advanced
454 **/
455 int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
456                                     CeedInt *numblock) {
457   *numblock = rstr->nblk;
458   return 0;
459 }
460 
461 /**
462   @brief Get the size of blocks in the CeedElemRestriction
463 
464   @param r                CeedElemRestriction
465   @param[out] blksize     Variable to store size of blocks
466 
467   @return An error code: 0 - success, otherwise - failure
468 
469   @ref Advanced
470 **/
471 int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
472                                     CeedInt *blksize) {
473   *blksize = rstr->blksize;
474   return 0;
475 }
476 
477 /**
478   @brief Get the backend data of a CeedElemRestriction
479 
480   @param r                CeedElemRestriction
481   @param[out] data        Variable to store data
482 
483   @return An error code: 0 - success, otherwise - failure
484 
485   @ref Advanced
486 **/
487 int CeedElemRestrictionGetData(CeedElemRestriction rstr,
488                                void* *data) {
489   *data = rstr->data;
490   return 0;
491 }
492 
493 /**
494   @brief Set the backend data of a CeedElemRestriction
495 
496   @param[out] r           CeedElemRestriction
497   @param data             Data to set
498 
499   @return An error code: 0 - success, otherwise - failure
500 
501   @ref Advanced
502 **/
503 int CeedElemRestrictionSetData(CeedElemRestriction rstr,
504                                void* *data) {
505   rstr->data = *data;
506   return 0;
507 }
508 
509 /**
510   @brief Destroy a CeedElemRestriction
511 
512   @param rstr CeedElemRestriction to destroy
513 
514   @return An error code: 0 - success, otherwise - failure
515 
516   @ref Basic
517 **/
518 int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
519   int ierr;
520 
521   if (!*rstr || --(*rstr)->refcount > 0) return 0;
522   if ((*rstr)->Destroy) {
523     ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr);
524   }
525   ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr);
526   ierr = CeedFree(rstr); CeedChk(ierr);
527   return 0;
528 }
529 
530 /// @}
531