xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-elemrestriction.c (revision d4fd2798a181527c7dae4b06bee398a0660820c5)
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 Restrict an L-vector to a block of an E-vector or apply transpose
313 
314   @param rstr    CeedElemRestriction
315   @param block   Block number to restrict to/from, i.e. block=0 will handle
316                  elements [0 : blksize] and block=3 will handle elements
317                  [3*blksize : 4*blksize]
318   @param tmode   Apply restriction or transpose
319   @param lmode   Ordering of the ncomp components
320   @param u       Input vector (of size @a ndof when tmode=CEED_NOTRANSPOSE)
321   @param v       Output vector (of size @a nelem * @a elemsize when tmode=CEED_NOTRANSPOSE)
322   @param request Request or CEED_REQUEST_IMMEDIATE
323 
324   @return An error code: 0 - success, otherwise - failure
325 
326   @ref Advanced
327 **/
328 int CeedElemRestrictionApplyBlock(CeedElemRestriction rstr, CeedInt block,
329                                   CeedTransposeMode tmode,
330                                   CeedTransposeMode lmode,
331                                   CeedVector u, CeedVector v,
332                                   CeedRequest *request) {
333   CeedInt m,n;
334   int ierr;
335 
336   if (tmode == CEED_NOTRANSPOSE) {
337     m = rstr->blksize * rstr->elemsize * rstr->ncomp;
338     n = rstr->ndof * rstr->ncomp;
339   } else {
340     m = rstr->ndof * rstr->ncomp;
341     n = rstr->blksize * rstr->elemsize * rstr->ncomp;
342   }
343   if (n != u->length)
344     return CeedError(rstr->ceed, 2,
345                      "Input vector size %d not compatible with element restriction (%d, %d)",
346                      u->length, m, n);
347   if (m != v->length)
348     return CeedError(rstr->ceed, 2,
349                      "Output vector size %d not compatible with element restriction (%d, %d)",
350                      v->length, m, n);
351   if (rstr->blksize*block > rstr->nelem)
352     return CeedError(rstr->ceed, 2,
353                      "Cannot retrieve block %d, element %d > total elements %d",
354                      block, rstr->blksize*block, rstr->nelem);
355   ierr = rstr->ApplyBlock(rstr, block, tmode, lmode, u, v, request);
356   CeedChk(ierr);
357 
358   return 0;
359 }
360 
361 /**
362   @brief Get the Ceed associated with a CeedElemRestriction
363 
364   @param rstr             CeedElemRestriction
365   @param[out] ceed        Variable to store Ceed
366 
367   @return An error code: 0 - success, otherwise - failure
368 
369   @ref Advanced
370 **/
371 int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
372   *ceed = rstr->ceed;
373   return 0;
374 }
375 
376 /**
377   @brief Get the total number of elements in the range of a CeedElemRestriction
378 
379   @param rstr             CeedElemRestriction
380   @param[out] numelements Variable to store number of elements
381 
382   @return An error code: 0 - success, otherwise - failure
383 
384   @ref Advanced
385 **/
386 int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
387                                       CeedInt *numelem) {
388   *numelem = rstr->nelem;
389   return 0;
390 }
391 
392 /**
393   @brief Get the size of elements in the CeedElemRestriction
394 
395   @param rstr             CeedElemRestriction
396   @param[out] elemsize    Variable to store size of elements
397 
398   @return An error code: 0 - success, otherwise - failure
399 
400   @ref Advanced
401 **/
402 int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
403                                       CeedInt *elemsize) {
404   *elemsize = rstr->elemsize;
405   return 0;
406 }
407 
408 /**
409   @brief Get the number of degrees of freedom in the range of a
410          CeedElemRestriction
411 
412   @param rstr             CeedElemRestriction
413   @param[out] numdof      Variable to store number of DoFs
414 
415   @return An error code: 0 - success, otherwise - failure
416 
417   @ref Advanced
418 **/
419 int CeedElemRestrictionGetNumDoF(CeedElemRestriction rstr,
420                                  CeedInt *numdof) {
421   *numdof = rstr->ndof;
422   return 0;
423 }
424 
425 /**
426   @brief Get the number of components in the elements of a
427          CeedElemRestriction
428 
429   @param rstr             CeedElemRestriction
430   @param[out] numcomp     Variable to store number of components
431 
432   @return An error code: 0 - success, otherwise - failure
433 
434   @ref Advanced
435 **/
436 int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
437                                         CeedInt *numcomp) {
438   *numcomp = rstr->ncomp;
439   return 0;
440 }
441 
442 /**
443   @brief Get the number of blocks in a CeedElemRestriction
444 
445   @param rstr             CeedElemRestriction
446   @param[out] numblock    Variable to store number of blocks
447 
448   @return An error code: 0 - success, otherwise - failure
449 
450   @ref Advanced
451 **/
452 int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
453                                     CeedInt *numblock) {
454   *numblock = rstr->nblk;
455   return 0;
456 }
457 
458 /**
459   @brief Get the size of blocks in the CeedElemRestriction
460 
461   @param r                CeedElemRestriction
462   @param[out] blksize     Variable to store size of blocks
463 
464   @return An error code: 0 - success, otherwise - failure
465 
466   @ref Advanced
467 **/
468 int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
469                                     CeedInt *blksize) {
470   *blksize = rstr->blksize;
471   return 0;
472 }
473 
474 /**
475   @brief Get the backend data of a CeedElemRestriction
476 
477   @param r                CeedElemRestriction
478   @param[out] data        Variable to store data
479 
480   @return An error code: 0 - success, otherwise - failure
481 
482   @ref Advanced
483 **/
484 int CeedElemRestrictionGetData(CeedElemRestriction rstr,
485                                void* *data) {
486   *data = rstr->data;
487   return 0;
488 }
489 
490 /**
491   @brief Set the backend data of a CeedElemRestriction
492 
493   @param[out] r           CeedElemRestriction
494   @param data             Data to set
495 
496   @return An error code: 0 - success, otherwise - failure
497 
498   @ref Advanced
499 **/
500 int CeedElemRestrictionSetData(CeedElemRestriction rstr,
501                                void* *data) {
502   rstr->data = *data;
503   return 0;
504 }
505 
506 /**
507   @brief Destroy a CeedElemRestriction
508 
509   @param rstr CeedElemRestriction to destroy
510 
511   @return An error code: 0 - success, otherwise - failure
512 
513   @ref Basic
514 **/
515 int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
516   int ierr;
517 
518   if (!*rstr || --(*rstr)->refcount > 0) return 0;
519   if ((*rstr)->Destroy) {
520     ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr);
521   }
522   ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr);
523   ierr = CeedFree(rstr); CeedChk(ierr);
524   return 0;
525 }
526 
527 /// @}
528