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