xref: /libCEED/interface/ceed-elemrestriction.c (revision 241a4b83dc9c714eb4bcc90729a46be02322143a)
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 multiplicity of DoFs in a CeedElemRestriction
366 
367   @param rstr      CeedElemRestriction
368   @param[out] mult Vector to store multiplicity (of size ndof)
369 
370   @return An error code: 0 - success, otherwise - failure
371 
372   @ref Advanced
373 **/
374 int CeedElemRestrictionGetMultiplicity(CeedElemRestriction rstr,
375                              CeedVector mult) {
376   int ierr;
377   CeedVector evec;
378 
379   // Create and set evec
380   ierr = CeedElemRestrictionCreateVector(rstr, NULL, &evec); CeedChk(ierr);
381   ierr = CeedVectorSetValue(evec, 1.0); CeedChk(ierr);
382 
383   // Apply to get multiplicity
384   ierr = CeedElemRestrictionApply(rstr, CEED_TRANSPOSE, CEED_NOTRANSPOSE, evec,
385                                   mult, CEED_REQUEST_IMMEDIATE); CeedChk(ierr);
386 
387   // Cleanup
388   ierr = CeedVectorDestroy(&evec); CeedChk(ierr);
389 
390   return 0;
391 }
392 
393 /**
394   @brief Get the Ceed associated with a CeedElemRestriction
395 
396   @param rstr             CeedElemRestriction
397   @param[out] ceed        Variable to store Ceed
398 
399   @return An error code: 0 - success, otherwise - failure
400 
401   @ref Advanced
402 **/
403 int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
404   *ceed = rstr->ceed;
405   return 0;
406 }
407 
408 /**
409   @brief Get the total number of elements in the range of a CeedElemRestriction
410 
411   @param rstr             CeedElemRestriction
412   @param[out] numelements Variable to store number of elements
413 
414   @return An error code: 0 - success, otherwise - failure
415 
416   @ref Advanced
417 **/
418 int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
419                                       CeedInt *numelem) {
420   *numelem = rstr->nelem;
421   return 0;
422 }
423 
424 /**
425   @brief Get the size of elements in the CeedElemRestriction
426 
427   @param rstr             CeedElemRestriction
428   @param[out] elemsize    Variable to store size of elements
429 
430   @return An error code: 0 - success, otherwise - failure
431 
432   @ref Advanced
433 **/
434 int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
435                                       CeedInt *elemsize) {
436   *elemsize = rstr->elemsize;
437   return 0;
438 }
439 
440 /**
441   @brief Get the number of degrees of freedom in the range of a
442          CeedElemRestriction
443 
444   @param rstr             CeedElemRestriction
445   @param[out] numdof      Variable to store number of DoFs
446 
447   @return An error code: 0 - success, otherwise - failure
448 
449   @ref Advanced
450 **/
451 int CeedElemRestrictionGetNumDoF(CeedElemRestriction rstr,
452                                  CeedInt *numdof) {
453   *numdof = rstr->ndof;
454   return 0;
455 }
456 
457 /**
458   @brief Get the number of components in the elements of a
459          CeedElemRestriction
460 
461   @param rstr             CeedElemRestriction
462   @param[out] numcomp     Variable to store number of components
463 
464   @return An error code: 0 - success, otherwise - failure
465 
466   @ref Advanced
467 **/
468 int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
469                                         CeedInt *numcomp) {
470   *numcomp = rstr->ncomp;
471   return 0;
472 }
473 
474 /**
475   @brief Get the number of blocks in a CeedElemRestriction
476 
477   @param rstr             CeedElemRestriction
478   @param[out] numblock    Variable to store number of blocks
479 
480   @return An error code: 0 - success, otherwise - failure
481 
482   @ref Advanced
483 **/
484 int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
485                                     CeedInt *numblock) {
486   *numblock = rstr->nblk;
487   return 0;
488 }
489 
490 /**
491   @brief Get the size of blocks in the CeedElemRestriction
492 
493   @param r                CeedElemRestriction
494   @param[out] blksize     Variable to store size of blocks
495 
496   @return An error code: 0 - success, otherwise - failure
497 
498   @ref Advanced
499 **/
500 int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
501                                     CeedInt *blksize) {
502   *blksize = rstr->blksize;
503   return 0;
504 }
505 
506 /**
507   @brief Get the backend data of a CeedElemRestriction
508 
509   @param r                CeedElemRestriction
510   @param[out] data        Variable to store data
511 
512   @return An error code: 0 - success, otherwise - failure
513 
514   @ref Advanced
515 **/
516 int CeedElemRestrictionGetData(CeedElemRestriction rstr,
517                                void* *data) {
518   *data = rstr->data;
519   return 0;
520 }
521 
522 /**
523   @brief Set the backend data of a CeedElemRestriction
524 
525   @param[out] r           CeedElemRestriction
526   @param data             Data to set
527 
528   @return An error code: 0 - success, otherwise - failure
529 
530   @ref Advanced
531 **/
532 int CeedElemRestrictionSetData(CeedElemRestriction rstr,
533                                void* *data) {
534   rstr->data = *data;
535   return 0;
536 }
537 
538 /**
539   @brief Destroy a CeedElemRestriction
540 
541   @param rstr CeedElemRestriction to destroy
542 
543   @return An error code: 0 - success, otherwise - failure
544 
545   @ref Basic
546 **/
547 int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
548   int ierr;
549 
550   if (!*rstr || --(*rstr)->refcount > 0) return 0;
551   if ((*rstr)->Destroy) {
552     ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr);
553   }
554   ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr);
555   ierr = CeedFree(rstr); CeedChk(ierr);
556   return 0;
557 }
558 
559 /// @}
560