xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-elemrestriction.c (revision 5fe0d4fa442f339208d7656a646e69da1442c2a1)
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] r     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 *r) {
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, r); CeedChk(ierr);
65     return 0;
66   }
67 
68   ierr = CeedCalloc(1, r); CeedChk(ierr);
69   (*r)->ceed = ceed;
70   ceed->refcount++;
71   (*r)->refcount = 1;
72   (*r)->nelem = nelem;
73   (*r)->elemsize = elemsize;
74   (*r)->ndof = ndof;
75   (*r)->ncomp = ncomp;
76   (*r)->nblk = nelem;
77   (*r)->blksize = 1;
78   ierr = ceed->ElemRestrictionCreate(mtype, cmode, indices, *r); 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 r          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 *r) {
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, r); CeedChk(ierr);
115     return 0;
116   }
117 
118   ierr = CeedCalloc(1, r); CeedChk(ierr);
119   (*r)->ceed = ceed;
120   ceed->refcount++;
121   (*r)->refcount = 1;
122   (*r)->nelem = nelem;
123   (*r)->elemsize = elemsize;
124   (*r)->ndof = ndof;
125   (*r)->ncomp = ncomp;
126   (*r)->nblk = nelem;
127   (*r)->blksize = 1;
128   ierr = ceed->ElemRestrictionCreate(CEED_MEM_HOST, CEED_OWN_POINTER, NULL, *r);
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 r          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, CeedElemRestriction *r) {
194   int ierr;
195   CeedInt *blkindices;
196   CeedInt nblk = (nelem / blksize) + !!(nelem % blksize);
197 
198   if (!ceed->ElemRestrictionCreateBlocked) {
199     Ceed delegate;
200     ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr);
201 
202     if (!delegate)
203       return CeedError(ceed, 1,
204                      "Backend does not support ElemRestrictionCreateBlocked");
205 
206     ierr = CeedElemRestrictionCreateBlocked(delegate, nelem, elemsize,
207                             blksize, ndof, ncomp, mtype, cmode,
208                             indices, r); CeedChk(ierr);
209     return 0;
210   }
211 
212   ierr = CeedCalloc(1, r); CeedChk(ierr);
213 
214   if (indices) {
215     ierr = CeedCalloc(nblk*blksize*elemsize, &blkindices);
216     ierr = CeedPermutePadIndices(indices, blkindices, nblk, nelem, blksize,
217                                  elemsize);
218     CeedChk(ierr);
219   } else {
220     blkindices = NULL;
221   }
222 
223   (*r)->ceed = ceed;
224   ceed->refcount++;
225   (*r)->refcount = 1;
226   (*r)->nelem = nelem;
227   (*r)->elemsize = elemsize;
228   (*r)->ndof = ndof;
229   (*r)->ncomp = ncomp;
230   (*r)->nblk = nblk;
231   (*r)->blksize = blksize;
232   ierr = ceed->ElemRestrictionCreateBlocked(CEED_MEM_HOST, CEED_OWN_POINTER,
233          (const CeedInt *) blkindices, *r);
234   CeedChk(ierr);
235 
236   if (cmode == CEED_OWN_POINTER)
237     ierr = CeedFree(&indices); CeedChk(ierr);
238 
239   return 0;
240 }
241 
242 /**
243   @brief Create CeedVectors associated with a CeedElemRestriction
244 
245   @param r     CeedElemRestriction
246   @param lvec  The address of the L-vector to be created, or NULL
247   @param evec  The address of the E-vector to be created, or NULL
248 
249   @return An error code: 0 - success, otherwise - failure
250 
251   @ref Advanced
252 **/
253 int CeedElemRestrictionCreateVector(CeedElemRestriction r, CeedVector *lvec,
254                                     CeedVector *evec) {
255   int ierr;
256   CeedInt n, m;
257   m = r->ndof * r->ncomp;
258   n = r->nblk * r->blksize * r->elemsize * r->ncomp;
259   if (lvec) {
260     ierr = CeedVectorCreate(r->ceed, m, lvec); CeedChk(ierr);
261   }
262   if (evec) {
263     ierr = CeedVectorCreate(r->ceed, n, evec); CeedChk(ierr);
264   }
265   return 0;
266 }
267 
268 /**
269   @brief Restrict an L-vector to an E-vector or apply transpose
270 
271   @param r       CeedElemRestriction
272   @param tmode   Apply restriction or transpose
273   @param lmode   Ordering of the ncomp components
274   @param u       Input vector (of size @a ndof when tmode=CEED_NOTRANSPOSE)
275   @param v       Output vector (of size @a nelem * @a elemsize when tmode=CEED_NOTRANSPOSE)
276   @param request Request or CEED_REQUEST_IMMEDIATE
277 
278   @return An error code: 0 - success, otherwise - failure
279 
280   @ref Advanced
281 **/
282 int CeedElemRestrictionApply(CeedElemRestriction r, CeedTransposeMode tmode,
283                              CeedTransposeMode lmode,
284                              CeedVector u, CeedVector v, CeedRequest *request) {
285   CeedInt m,n;
286   int ierr;
287 
288   if (tmode == CEED_NOTRANSPOSE) {
289     m = r->nblk * r->blksize * r->elemsize * r->ncomp;
290     n = r->ndof * r->ncomp;
291   } else {
292     m = r->ndof * r->ncomp;
293     n = r->nblk * r->blksize * r->elemsize * r->ncomp;
294   }
295   if (n != u->length)
296     return CeedError(r->ceed, 2,
297                      "Input vector size %d not compatible with element restriction (%d, %d)",
298                      u->length, m, n);
299   if (m != v->length)
300     return CeedError(r->ceed, 2,
301                      "Output vector size %d not compatible with element restriction (%d, %d)",
302                      v->length, m, n);
303   ierr = r->Apply(r, tmode, lmode, u, v, request); CeedChk(ierr);
304 
305   return 0;
306 }
307 
308 /**
309   @brief Get the total number of elements in the range of a CeedElemRestriction
310 
311   @param r                CeedElemRestriction
312   @param[out] numelements Number of elements
313 
314   @return An error code: 0 - success, otherwise - failure
315 
316   @ref Utility
317 **/
318 int CeedElemRestrictionGetNumElements(CeedElemRestriction r,
319                                       CeedInt *numelements) {
320   *numelements = r->nelem;
321   return 0;
322 }
323 
324 /**
325   @brief Destroy a CeedElemRestriction
326 
327   @param r CeedElemRestriction to destroy
328 
329   @return An error code: 0 - success, otherwise - failure
330 
331   @ref Basic
332 **/
333 int CeedElemRestrictionDestroy(CeedElemRestriction *r) {
334   int ierr;
335 
336   if (!*r || --(*r)->refcount > 0) return 0;
337   if ((*r)->Destroy) {
338     ierr = (*r)->Destroy(*r); CeedChk(ierr);
339   }
340   ierr = CeedDestroy(&(*r)->ceed); CeedChk(ierr);
341   ierr = CeedFree(r); CeedChk(ierr);
342   return 0;
343 }
344 
345 /// @}
346