xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-elemrestriction.c (revision f82d2baa7ca109f28fd503bf3902b2ceeba90030)
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     return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
57   ierr = CeedCalloc(1, r); CeedChk(ierr);
58   (*r)->ceed = ceed;
59   ceed->refcount++;
60   (*r)->refcount = 1;
61   (*r)->nelem = nelem;
62   (*r)->elemsize = elemsize;
63   (*r)->ndof = ndof;
64   (*r)->ncomp = ncomp;
65   (*r)->nblk = nelem;
66   (*r)->blksize = 1;
67   ierr = ceed->ElemRestrictionCreate(*r, mtype, cmode, indices); CeedChk(ierr);
68   return 0;
69 }
70 
71 /**
72   @brief Create an identity CeedElemRestriction
73 
74   @param ceed       A Ceed object where the CeedElemRestriction will be created
75   @param nelem      Number of elements described in the @a indices array
76   @param elemsize   Size (number of "nodes") per element
77   @param ndof       The total size of the input CeedVector to which the
78                       restriction will be applied. This size may include data
79                       used by other CeedElemRestriction objects describing
80                       different types of elements
81   @param ncomp      Number of field components per interpolation node
82   @param r          Address of the variable where the newly created
83                       CeedElemRestriction will be stored
84 
85   @return An error code: 0 - success, otherwise - failure
86 
87   @ref Basic
88 **/
89 int CeedElemRestrictionCreateIdentity(Ceed ceed, CeedInt nelem,
90                                       CeedInt elemsize,
91                                       CeedInt ndof, CeedInt ncomp, CeedElemRestriction *r) {
92   int ierr;
93 
94   if (!ceed->ElemRestrictionCreate)
95     return CeedError(ceed, 1,
96                      "Backend does not support ElemRestrictionCreateIdentity");
97   ierr = CeedCalloc(1, r); CeedChk(ierr);
98   (*r)->ceed = ceed;
99   ceed->refcount++;
100   (*r)->refcount = 1;
101   (*r)->nelem = nelem;
102   (*r)->elemsize = elemsize;
103   (*r)->ndof = ndof;
104   (*r)->ncomp = ncomp;
105   (*r)->nblk = nelem;
106   (*r)->blksize = 1;
107   ierr = ceed->ElemRestrictionCreate(*r, CEED_MEM_HOST, CEED_OWN_POINTER, NULL);
108   CeedChk(ierr);
109   return 0;
110 }
111 
112 /**
113   @brief Permute and pad indices for a blocked restriction
114 
115   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the ordered list
116                       of the indices (into the input CeedVector) for the unknowns
117                       corresponding to element i, where 0 <= i < @a nelements.
118                       All indices must be in the range [0, @a ndof).
119   @param blkindices Array of permuted and padded indices of
120                       shape [@a nblk, @a elemsize, @a blksize].
121   @param nblk       Number of blocks
122   @param nelem      Number of elements
123   @param blksize    Number of elements in a block
124   @param elemsize   Size of each element
125 
126   @return An error code: 0 - success, otherwise - failure
127 
128   @ref Utility
129 **/
130 int CeedPermutePadIndices(const CeedInt *indices, CeedInt *blkindices,
131                           CeedInt nblk, CeedInt nelem,
132                           CeedInt blksize, CeedInt elemsize) {
133   for (CeedInt e = 0; e < nblk*blksize; e+=blksize)
134     for (int j = 0; j < blksize; j++)
135       for (int k = 0; k < elemsize; k++)
136         blkindices[e*elemsize + k*blksize + j]
137           = indices[CeedIntMin(e+j,nelem-1)*elemsize + k];
138   return 0;
139 }
140 
141 /**
142   @brief Create a blocked CeedElemRestriction, typically only called by backends
143 
144   @param ceed       A Ceed object where the CeedElemRestriction will be created.
145   @param nelem      Number of elements described in the @a indices array.
146   @param elemsize   Size (number of unknowns) per element
147   @param blksize    Number of elements in a block
148   @param ndof       The total size of the input CeedVector to which the
149                       restriction will be applied. This size may include data
150                       used by other CeedElemRestriction objects describing
151                       different types of elements.
152   @param ncomp      Number of components stored at each node
153   @param mtype      Memory type of the @a indices array, see CeedMemType
154   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
155   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the ordered list
156                       of the indices (into the input CeedVector) for the unknowns
157                       corresponding to element i, where 0 <= i < @a nelements.
158                       All indices must be in the range [0, @a ndof). The
159                       backend will permute and pad this array to the desired
160                       ordering for the blocksize, which is typically given by the
161                       backend. The default reordering is to interlace elements.
162   @param r          Address of the variable where the newly created
163                       CeedElemRestriction will be stored
164 
165   @return An error code: 0 - success, otherwise - failure
166 
167   @ref Advanced
168  **/
169 int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt nelem, CeedInt elemsize,
170                                      CeedInt blksize, CeedInt ndof, CeedInt ncomp,
171                                      CeedMemType mtype, CeedCopyMode cmode,
172                                      const CeedInt *indices, CeedElemRestriction *r) {
173   int ierr;
174   CeedInt *blkindices;
175   CeedInt nblk = (nelem / blksize) + !!(nelem % blksize);
176 
177   if (!ceed->ElemRestrictionCreateBlocked)
178     return CeedError(ceed, 1,
179                      "Backend does not support ElemRestrictionCreateBlocked");
180   if (mtype != CEED_MEM_HOST)
181     return CeedError(ceed, 1, "Only MemType = HOST supported");
182 
183   ierr = CeedCalloc(1, r); CeedChk(ierr);
184 
185   if (indices) {
186     ierr = CeedCalloc(nblk*blksize*elemsize, &blkindices);
187     ierr = CeedPermutePadIndices(indices, blkindices, nblk, nelem, blksize,
188                                  elemsize);
189     CeedChk(ierr);
190   } else {
191     blkindices = NULL;
192   }
193 
194   (*r)->ceed = ceed;
195   ceed->refcount++;
196   (*r)->refcount = 1;
197   (*r)->nelem = nelem;
198   (*r)->elemsize = elemsize;
199   (*r)->ndof = ndof;
200   (*r)->ncomp = ncomp;
201   (*r)->nblk = nblk;
202   (*r)->blksize = blksize;
203   ierr = ceed->ElemRestrictionCreateBlocked(*r, CEED_MEM_HOST, CEED_OWN_POINTER,
204          (const CeedInt *) blkindices);
205   CeedChk(ierr);
206 
207   if (cmode == CEED_OWN_POINTER)
208     ierr = CeedFree(&indices); CeedChk(ierr);
209 
210   return 0;
211 }
212 
213 /**
214   @brief Create CeedVectors associated with a CeedElemRestriction
215 
216   @param r     CeedElemRestriction
217   @param lvec  The address of the L-vector to be created, or NULL
218   @param evec  The address of the E-vector to be created, or NULL
219 
220   @return An error code: 0 - success, otherwise - failure
221 
222   @ref Advanced
223 **/
224 int CeedElemRestrictionCreateVector(CeedElemRestriction r, CeedVector *lvec,
225                                     CeedVector *evec) {
226   int ierr;
227   CeedInt n, m;
228   m = r->ndof * r->ncomp;
229   n = r->nblk * r->blksize * r->elemsize * r->ncomp;
230   if (lvec) {
231     ierr = CeedVectorCreate(r->ceed, m, lvec); CeedChk(ierr);
232   }
233   if (evec) {
234     ierr = CeedVectorCreate(r->ceed, n, evec); CeedChk(ierr);
235   }
236   return 0;
237 }
238 
239 /**
240   @brief Restrict an L-vector to an E-vector or apply transpose
241 
242   @param r       CeedElemRestriction
243   @param tmode   Apply restriction or transpose
244   @param lmode   Ordering of the ncomp components
245   @param u       Input vector (of size @a ndof when tmode=CEED_NOTRANSPOSE)
246   @param v       Output vector (of size @a nelem * @a elemsize when tmode=CEED_NOTRANSPOSE)
247   @param request Request or CEED_REQUEST_IMMEDIATE
248 
249   @return An error code: 0 - success, otherwise - failure
250 
251   @ref Advanced
252 **/
253 int CeedElemRestrictionApply(CeedElemRestriction r, CeedTransposeMode tmode,
254                              CeedTransposeMode lmode,
255                              CeedVector u, CeedVector v, CeedRequest *request) {
256   CeedInt m,n;
257   int ierr;
258 
259   if (tmode == CEED_NOTRANSPOSE) {
260     m = r->nblk * r->blksize * r->elemsize * r->ncomp;
261     n = r->ndof * r->ncomp;
262   } else {
263     m = r->ndof * r->ncomp;
264     n = r->nblk * r->blksize * r->elemsize * r->ncomp;
265   }
266   if (n != u->length)
267     return CeedError(r->ceed, 2,
268                      "Input vector size %d not compatible with element restriction (%d, %d)",
269                      u->length, m, n);
270   if (m != v->length)
271     return CeedError(r->ceed, 2,
272                      "Output vector size %d not compatible with element restriction (%d, %d)",
273                      v->length, m, n);
274   ierr = r->Apply(r, tmode, lmode, u, v, request); CeedChk(ierr);
275 
276   return 0;
277 }
278 
279 /**
280   @brief Get the total number of elements in the range of a CeedElemRestriction
281 
282   @param r                CeedElemRestriction
283   @param[out] numelements Number of elements
284 
285   @return An error code: 0 - success, otherwise - failure
286 
287   @ref Utility
288 **/
289 int CeedElemRestrictionGetNumElements(CeedElemRestriction r,
290                                       CeedInt *numelements) {
291   *numelements = r->nelem;
292   return 0;
293 }
294 
295 /**
296   @brief Destroy a CeedElemRestriction
297 
298   @param r CeedElemRestriction to destroy
299 
300   @return An error code: 0 - success, otherwise - failure
301 
302   @ref Basic
303 **/
304 int CeedElemRestrictionDestroy(CeedElemRestriction *r) {
305   int ierr;
306 
307   if (!*r || --(*r)->refcount > 0) return 0;
308   if ((*r)->Destroy) {
309     ierr = (*r)->Destroy(*r); CeedChk(ierr);
310   }
311   ierr = CeedDestroy(&(*r)->ceed); CeedChk(ierr);
312   ierr = CeedFree(r); CeedChk(ierr);
313   return 0;
314 }
315 
316 /// @}
317