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