xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-elemrestriction.c (revision 23617272b99b7e9f8a74525161c55d44882cf4b4)
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, *rstr);
130   CeedChk(ierr);
131   return 0;
132 }
133 
134 /**
135   @brief Permute and pad indices for a blocked restriction
136 
137   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the ordered list
138                       of the indices (into the input CeedVector) for the unknowns
139                       corresponding to element i, where 0 <= i < @a nelements.
140                       All indices must be in the range [0, @a ndof).
141   @param blkindices Array of permuted and padded indices of
142                       shape [@a nblk, @a elemsize, @a blksize].
143   @param nblk       Number of blocks
144   @param nelem      Number of elements
145   @param blksize    Number of elements in a block
146   @param elemsize   Size of each element
147 
148   @return An error code: 0 - success, otherwise - failure
149 
150   @ref Utility
151 **/
152 int CeedPermutePadIndices(const CeedInt *indices, CeedInt *blkindices,
153                           CeedInt nblk, CeedInt nelem,
154                           CeedInt blksize, CeedInt elemsize) {
155   for (CeedInt e = 0; e < nblk*blksize; e+=blksize)
156     for (int j = 0; j < blksize; j++)
157       for (int k = 0; k < elemsize; k++)
158         blkindices[e*elemsize + k*blksize + j]
159           = indices[CeedIntMin(e+j,nelem-1)*elemsize + k];
160   return 0;
161 }
162 
163 /**
164   @brief Create a blocked CeedElemRestriction, typically only called by backends
165 
166   @param ceed       A Ceed object where the CeedElemRestriction will be created.
167   @param nelem      Number of elements described in the @a indices array.
168   @param elemsize   Size (number of unknowns) per element
169   @param blksize    Number of elements in a block
170   @param ndof       The total size of the input CeedVector to which the
171                       restriction will be applied. This size may include data
172                       used by other CeedElemRestriction objects describing
173                       different types of elements.
174   @param ncomp      Number of components stored at each node
175   @param mtype      Memory type of the @a indices array, see CeedMemType
176   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
177   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the ordered list
178                       of the indices (into the input CeedVector) for the unknowns
179                       corresponding to element i, where 0 <= i < @a nelements.
180                       All indices must be in the range [0, @a ndof). The
181                       backend will permute and pad this array to the desired
182                       ordering for the blocksize, which is typically given by the
183                       backend. The default reordering is to interlace elements.
184   @param rstr       Address of the variable where the newly created
185                       CeedElemRestriction will be stored
186 
187   @return An error code: 0 - success, otherwise - failure
188 
189   @ref Advanced
190  **/
191 int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt nelem, CeedInt elemsize,
192                                      CeedInt blksize, CeedInt ndof, CeedInt ncomp,
193                                      CeedMemType mtype, CeedCopyMode cmode,
194                                      const CeedInt *indices,
195                                      CeedElemRestriction *rstr) {
196   int ierr;
197   CeedInt *blkindices;
198   CeedInt nblk = (nelem / blksize) + !!(nelem % blksize);
199 
200   if (!ceed->ElemRestrictionCreateBlocked) {
201     Ceed delegate;
202     ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr);
203 
204     if (!delegate)
205       return CeedError(ceed, 1,
206                      "Backend does not support ElemRestrictionCreateBlocked");
207 
208     ierr = CeedElemRestrictionCreateBlocked(delegate, nelem, elemsize,
209                             blksize, ndof, ncomp, mtype, cmode,
210                             indices, rstr); CeedChk(ierr);
211     return 0;
212   }
213 
214   ierr = CeedCalloc(1, rstr); CeedChk(ierr);
215 
216   if (indices) {
217     ierr = CeedCalloc(nblk*blksize*elemsize, &blkindices);
218     ierr = CeedPermutePadIndices(indices, blkindices, nblk, nelem, blksize,
219                                  elemsize);
220     CeedChk(ierr);
221   } else {
222     blkindices = NULL;
223   }
224 
225   (*rstr)->ceed = ceed;
226   ceed->refcount++;
227   (*rstr)->refcount = 1;
228   (*rstr)->nelem = nelem;
229   (*rstr)->elemsize = elemsize;
230   (*rstr)->ndof = ndof;
231   (*rstr)->ncomp = ncomp;
232   (*rstr)->nblk = nblk;
233   (*rstr)->blksize = blksize;
234   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
235          (const CeedInt *) blkindices, *rstr);
236   CeedChk(ierr);
237 
238   if (cmode == CEED_OWN_POINTER)
239     ierr = CeedFree(&indices); CeedChk(ierr);
240 
241   return 0;
242 }
243 
244 /**
245   @brief Create CeedVectors associated with a CeedElemRestriction
246 
247   @param rstr  CeedElemRestriction
248   @param lvec  The address of the L-vector to be created, or NULL
249   @param evec  The address of the E-vector to be created, or NULL
250 
251   @return An error code: 0 - success, otherwise - failure
252 
253   @ref Advanced
254 **/
255 int CeedElemRestrictionCreateVector(CeedElemRestriction rstr, CeedVector *lvec,
256                                     CeedVector *evec) {
257   int ierr;
258   CeedInt n, m;
259   m = rstr->ndof * rstr->ncomp;
260   n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
261   if (lvec) {
262     ierr = CeedVectorCreate(rstr->ceed, m, lvec); CeedChk(ierr);
263   }
264   if (evec) {
265     ierr = CeedVectorCreate(rstr->ceed, n, evec); CeedChk(ierr);
266   }
267   return 0;
268 }
269 
270 /**
271   @brief Restrict an L-vector to an E-vector or apply transpose
272 
273   @param rstr    CeedElemRestriction
274   @param tmode   Apply restriction or transpose
275   @param lmode   Ordering of the ncomp components
276   @param u       Input vector (of size @a ndof when tmode=CEED_NOTRANSPOSE)
277   @param v       Output vector (of size @a nelem * @a elemsize when tmode=CEED_NOTRANSPOSE)
278   @param request Request or CEED_REQUEST_IMMEDIATE
279 
280   @return An error code: 0 - success, otherwise - failure
281 
282   @ref Advanced
283 **/
284 int CeedElemRestrictionApply(CeedElemRestriction rstr, CeedTransposeMode tmode,
285                              CeedTransposeMode lmode,
286                              CeedVector u, CeedVector v, CeedRequest *request) {
287   CeedInt m,n;
288   int ierr;
289 
290   if (tmode == CEED_NOTRANSPOSE) {
291     m = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
292     n = rstr->ndof * rstr->ncomp;
293   } else {
294     m = rstr->ndof * rstr->ncomp;
295     n = rstr->nblk * rstr->blksize * rstr->elemsize * rstr->ncomp;
296   }
297   if (n != u->length)
298     return CeedError(rstr->ceed, 2,
299                      "Input vector size %d not compatible with element restriction (%d, %d)",
300                      u->length, m, n);
301   if (m != v->length)
302     return CeedError(rstr->ceed, 2,
303                      "Output vector size %d not compatible with element restriction (%d, %d)",
304                      v->length, m, n);
305   ierr = rstr->Apply(rstr, tmode, lmode, u, v, request); CeedChk(ierr);
306 
307   return 0;
308 }
309 
310 /**
311   @brief Get the Ceed associated with a CeedElemRestriction
312 
313   @param rstr             CeedElemRestriction
314   @param[out] ceed        Variable to store Ceed
315 
316   @return An error code: 0 - success, otherwise - failure
317 
318   @ref Advanced
319 **/
320 int CeedElemRestrictionGetCeed(CeedElemRestriction rstr, Ceed *ceed) {
321   *ceed = rstr->ceed;
322   return 0;
323 }
324 
325 /**
326   @brief Get the total number of elements in the range of a CeedElemRestriction
327 
328   @param rstr             CeedElemRestriction
329   @param[out] numelements Variable to store number of elements
330 
331   @return An error code: 0 - success, otherwise - failure
332 
333   @ref Advanced
334 **/
335 int CeedElemRestrictionGetNumElements(CeedElemRestriction rstr,
336                                       CeedInt *numelem) {
337   *numelem = rstr->nelem;
338   return 0;
339 }
340 
341 /**
342   @brief Get the size of elements in the CeedElemRestriction
343 
344   @param rstr             CeedElemRestriction
345   @param[out] elemsize    Variable to store size of elements
346 
347   @return An error code: 0 - success, otherwise - failure
348 
349   @ref Advanced
350 **/
351 int CeedElemRestrictionGetElementSize(CeedElemRestriction rstr,
352                                    CeedInt *elemsize) {
353   *elemsize = rstr->elemsize;
354   return 0;
355 }
356 
357 /**
358   @brief Get the number of degrees of freedom in the range of a
359          CeedElemRestriction
360 
361   @param rstr             CeedElemRestriction
362   @param[out] numdof      Variable to store number of DoFs
363 
364   @return An error code: 0 - success, otherwise - failure
365 
366   @ref Advanced
367 **/
368 int CeedElemRestrictionGetNumDoF(CeedElemRestriction rstr,
369                                  CeedInt *numdof) {
370   *numdof = rstr->ndof;
371   return 0;
372 }
373 
374 /**
375   @brief Get the number of components in the elements of a
376          CeedElemRestriction
377 
378   @param rstr             CeedElemRestriction
379   @param[out] numcomp     Variable to store number of components
380 
381   @return An error code: 0 - success, otherwise - failure
382 
383   @ref Advanced
384 **/
385 int CeedElemRestrictionGetNumComponents(CeedElemRestriction rstr,
386                                   CeedInt *numcomp) {
387   *numcomp = rstr->ncomp;
388   return 0;
389 }
390 
391 /**
392   @brief Get the number of blocks in a CeedElemRestriction
393 
394   @param rstr             CeedElemRestriction
395   @param[out] numblock    Variable to store number of blocks
396 
397   @return An error code: 0 - success, otherwise - failure
398 
399   @ref Advanced
400 **/
401 int CeedElemRestrictionGetNumBlocks(CeedElemRestriction rstr,
402                                   CeedInt *numblock) {
403   *numblock = rstr->nblk;
404   return 0;
405 }
406 
407 /**
408   @brief Get the size of blocks in the CeedElemRestriction
409 
410   @param r                CeedElemRestriction
411   @param[out] blksize     Variable to store size of blocks
412 
413   @return An error code: 0 - success, otherwise - failure
414 
415   @ref Advanced
416 **/
417 int CeedElemRestrictionGetBlockSize(CeedElemRestriction rstr,
418                                     CeedInt *blksize) {
419   *blksize = rstr->blksize;
420   return 0;
421 }
422 
423 /**
424   @brief Get the backend data of a CeedElemRestriction
425 
426   @param r                CeedElemRestriction
427   @param[out] data        Variable to store data
428 
429   @return An error code: 0 - success, otherwise - failure
430 
431   @ref Advanced
432 **/
433 int CeedElemRestrictionGetData(CeedElemRestriction rstr,
434                                     void* *data) {
435   *data = rstr->data;
436   return 0;
437 }
438 
439 /**
440   @brief Destroy a CeedElemRestriction
441 
442   @param rstr CeedElemRestriction to destroy
443 
444   @return An error code: 0 - success, otherwise - failure
445 
446   @ref Basic
447 **/
448 int CeedElemRestrictionDestroy(CeedElemRestriction *rstr) {
449   int ierr;
450 
451   if (!*rstr || --(*rstr)->refcount > 0) return 0;
452   if ((*rstr)->Destroy) {
453     ierr = (*rstr)->Destroy(*rstr); CeedChk(ierr);
454   }
455   ierr = CeedDestroy(&(*rstr)->ceed); CeedChk(ierr);
456   ierr = CeedFree(rstr); CeedChk(ierr);
457   return 0;
458 }
459 
460 /// @}
461