xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-elemrestriction.c (revision 4b8bea3b15f6e9705ea378b18162a3dbd250c6ec)
1d7b241e6Sjeremylt // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2d7b241e6Sjeremylt // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3d7b241e6Sjeremylt // reserved. See files LICENSE and NOTICE for details.
4d7b241e6Sjeremylt //
5d7b241e6Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software
6d7b241e6Sjeremylt // libraries and APIs for efficient high-order finite element and spectral
7d7b241e6Sjeremylt // element discretizations for exascale applications. For more information and
8d7b241e6Sjeremylt // source code availability see http://github.com/ceed.
9d7b241e6Sjeremylt //
10d7b241e6Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11d7b241e6Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office
12d7b241e6Sjeremylt // of Science and the National Nuclear Security Administration) responsible for
13d7b241e6Sjeremylt // the planning and preparation of a capable exascale ecosystem, including
14d7b241e6Sjeremylt // software, applications, hardware, advanced system engineering and early
15d7b241e6Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative.
16d7b241e6Sjeremylt 
17d7b241e6Sjeremylt #include <ceed-impl.h>
18d7b241e6Sjeremylt 
19d7b241e6Sjeremylt /// @file
20d7b241e6Sjeremylt /// Implementation of public CeedElemRestriction interfaces
21d7b241e6Sjeremylt ///
22dfdf5a53Sjeremylt /// @addtogroup CeedElemRestriction
23d7b241e6Sjeremylt /// @{
24d7b241e6Sjeremylt 
25d7b241e6Sjeremylt /**
26b11c1e72Sjeremylt   @brief Create a CeedElemRestriction
27d7b241e6Sjeremylt 
28b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
29b11c1e72Sjeremylt   @param nelem      Number of elements described in the @a indices array
30b11c1e72Sjeremylt   @param elemsize   Size (number of "nodes") per element
31d7b241e6Sjeremylt   @param ndof       The total size of the input CeedVector to which the
32d7b241e6Sjeremylt                       restriction will be applied. This size may include data
33d7b241e6Sjeremylt                       used by other CeedElemRestriction objects describing
34d7b241e6Sjeremylt                       different types of elements.
35b11c1e72Sjeremylt   @param ncomp      Number of field components per interpolation node
36b11c1e72Sjeremylt   @param mtype      Memory type of the @a indices array, see CeedMemType
37b11c1e72Sjeremylt   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
38ecf6354eSJed Brown   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the ordered list
39d7b241e6Sjeremylt                       of the indices (into the input CeedVector) for the unknowns
40d7b241e6Sjeremylt                       corresponding to element i, where 0 <= i < @a nelements.
41d7b241e6Sjeremylt                       All indices must be in the range [0, @a ndof).
42b11c1e72Sjeremylt   @param[out] r     Address of the variable where the newly created
43b11c1e72Sjeremylt                       CeedElemRestriction will be stored
44d7b241e6Sjeremylt 
45b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
46dfdf5a53Sjeremylt 
47dfdf5a53Sjeremylt   @ref Basic
48b11c1e72Sjeremylt **/
49d7b241e6Sjeremylt int CeedElemRestrictionCreate(Ceed ceed, CeedInt nelem, CeedInt elemsize,
50d7b241e6Sjeremylt                               CeedInt ndof, CeedInt ncomp, CeedMemType mtype,
51d7b241e6Sjeremylt                               CeedCopyMode cmode, const CeedInt *indices,
52d7b241e6Sjeremylt                               CeedElemRestriction *r) {
53d7b241e6Sjeremylt   int ierr;
54d7b241e6Sjeremylt 
55d7b241e6Sjeremylt   if (!ceed->ElemRestrictionCreate)
56d7b241e6Sjeremylt     return CeedError(ceed, 1, "Backend does not support ElemRestrictionCreate");
57d7b241e6Sjeremylt   ierr = CeedCalloc(1, r); CeedChk(ierr);
58d7b241e6Sjeremylt   (*r)->ceed = ceed;
59d7b241e6Sjeremylt   ceed->refcount++;
60d7b241e6Sjeremylt   (*r)->refcount = 1;
61d7b241e6Sjeremylt   (*r)->nelem = nelem;
62d7b241e6Sjeremylt   (*r)->elemsize = elemsize;
63d7b241e6Sjeremylt   (*r)->ndof = ndof;
64d7b241e6Sjeremylt   (*r)->ncomp = ncomp;
65d7b241e6Sjeremylt   (*r)->nblk = nelem;
66d7b241e6Sjeremylt   (*r)->blksize = 1;
67d7b241e6Sjeremylt   ierr = ceed->ElemRestrictionCreate(*r, mtype, cmode, indices); CeedChk(ierr);
68d7b241e6Sjeremylt   return 0;
69d7b241e6Sjeremylt }
70d7b241e6Sjeremylt 
71d7b241e6Sjeremylt /**
72b11c1e72Sjeremylt   @brief Create an identity CeedElemRestriction
73d7b241e6Sjeremylt 
74b11c1e72Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created
75b11c1e72Sjeremylt   @param nelem      Number of elements described in the @a indices array
76b11c1e72Sjeremylt   @param elemsize   Size (number of "nodes") per element
77d7b241e6Sjeremylt   @param ndof       The total size of the input CeedVector to which the
78d7b241e6Sjeremylt                       restriction will be applied. This size may include data
79d7b241e6Sjeremylt                       used by other CeedElemRestriction objects describing
80b11c1e72Sjeremylt                       different types of elements
81b11c1e72Sjeremylt   @param ncomp      Number of field components per interpolation node
82b11c1e72Sjeremylt   @param r          Address of the variable where the newly created
83b11c1e72Sjeremylt                       CeedElemRestriction will be stored
84d7b241e6Sjeremylt 
85b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
86dfdf5a53Sjeremylt 
87dfdf5a53Sjeremylt   @ref Basic
88b11c1e72Sjeremylt **/
89*4b8bea3bSJed Brown int CeedElemRestrictionCreateIdentity(Ceed ceed, CeedInt nelem,
90*4b8bea3bSJed Brown                                       CeedInt elemsize,
91d7b241e6Sjeremylt                                       CeedInt ndof, CeedInt ncomp, CeedElemRestriction *r) {
92d7b241e6Sjeremylt   int ierr;
93d7b241e6Sjeremylt 
94d7b241e6Sjeremylt   if (!ceed->ElemRestrictionCreate)
95*4b8bea3bSJed Brown     return CeedError(ceed, 1,
96*4b8bea3bSJed Brown                      "Backend does not support ElemRestrictionCreateIdentity");
97d7b241e6Sjeremylt   ierr = CeedCalloc(1, r); CeedChk(ierr);
98d7b241e6Sjeremylt   (*r)->ceed = ceed;
99d7b241e6Sjeremylt   ceed->refcount++;
100d7b241e6Sjeremylt   (*r)->refcount = 1;
101d7b241e6Sjeremylt   (*r)->nelem = nelem;
102d7b241e6Sjeremylt   (*r)->elemsize = elemsize;
103d7b241e6Sjeremylt   (*r)->ndof = ndof;
104d7b241e6Sjeremylt   (*r)->ncomp = ncomp;
105d7b241e6Sjeremylt   (*r)->nblk = nelem;
106d7b241e6Sjeremylt   (*r)->blksize = 1;
107*4b8bea3bSJed Brown   ierr = ceed->ElemRestrictionCreate(*r, CEED_MEM_HOST, CEED_OWN_POINTER, NULL);
108*4b8bea3bSJed Brown   CeedChk(ierr);
109d7b241e6Sjeremylt   return 0;
110d7b241e6Sjeremylt }
111d7b241e6Sjeremylt 
112d7b241e6Sjeremylt /**
113b11c1e72Sjeremylt   @brief Permute and pad indices for a blocked restriction
114d7b241e6Sjeremylt 
115ecf6354eSJed Brown   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the ordered list
116d7b241e6Sjeremylt                       of the indices (into the input CeedVector) for the unknowns
117d7b241e6Sjeremylt                       corresponding to element i, where 0 <= i < @a nelements.
118d7b241e6Sjeremylt                       All indices must be in the range [0, @a ndof).
119ecf6354eSJed Brown   @param blkindices Array of permuted and padded indices of
120ecf6354eSJed Brown                       shape [@a nblk, @a elemsize, @a blksize].
121d7b241e6Sjeremylt   @param nblk       Number of blocks
122d7b241e6Sjeremylt   @param nelem      Number of elements
123d7b241e6Sjeremylt   @param blksize    Number of elements in a block
124d7b241e6Sjeremylt   @param elemsize   Size of each element
125d7b241e6Sjeremylt 
126b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
127b11c1e72Sjeremylt 
128dfdf5a53Sjeremylt   @ref Utility
129b11c1e72Sjeremylt **/
130dfdf5a53Sjeremylt int CeedPermutePadIndices(const CeedInt *indices, CeedInt *blkindices,
131d7b241e6Sjeremylt                           CeedInt nblk, CeedInt nelem,
132d7b241e6Sjeremylt                           CeedInt blksize, CeedInt elemsize) {
133d7b241e6Sjeremylt   for (CeedInt e = 0; e < nblk*blksize; e+=blksize)
134d7b241e6Sjeremylt     for (int j = 0; j < blksize; j++)
135d7b241e6Sjeremylt       for (int k = 0; k < elemsize; k++)
136d7b241e6Sjeremylt         blkindices[e*elemsize + k*blksize + j]
137d7b241e6Sjeremylt           = indices[CeedIntMin(e+j,nelem-1)*elemsize + k];
138dfdf5a53Sjeremylt   return 0;
139d7b241e6Sjeremylt }
140d7b241e6Sjeremylt 
141d7b241e6Sjeremylt /**
142b11c1e72Sjeremylt   @brief Create a blocked CeedElemRestriction, typically only called by backends
143d7b241e6Sjeremylt 
144d7b241e6Sjeremylt   @param ceed       A Ceed object where the CeedElemRestriction will be created.
145d7b241e6Sjeremylt   @param nelem      Number of elements described in the @a indices array.
146b11c1e72Sjeremylt   @param elemsize   Size (number of unknowns) per element
147b11c1e72Sjeremylt   @param blksize    Number of elements in a block
148d7b241e6Sjeremylt   @param ndof       The total size of the input CeedVector to which the
149d7b241e6Sjeremylt                       restriction will be applied. This size may include data
150d7b241e6Sjeremylt                       used by other CeedElemRestriction objects describing
151d7b241e6Sjeremylt                       different types of elements.
152b11c1e72Sjeremylt   @param ncomp      Number of components stored at each node
153b11c1e72Sjeremylt   @param mtype      Memory type of the @a indices array, see CeedMemType
154b11c1e72Sjeremylt   @param cmode      Copy mode for the @a indices array, see CeedCopyMode
155ecf6354eSJed Brown   @param indices    Array of shape [@a nelem, @a elemsize]. Row i holds the ordered list
156d7b241e6Sjeremylt                       of the indices (into the input CeedVector) for the unknowns
157d7b241e6Sjeremylt                       corresponding to element i, where 0 <= i < @a nelements.
158d7b241e6Sjeremylt                       All indices must be in the range [0, @a ndof). The
159d7b241e6Sjeremylt                       backend will permute and pad this array to the desired
160d7b241e6Sjeremylt                       ordering for the blocksize, which is typically given by the
161d7b241e6Sjeremylt                       backend. The default reordering is to interlace elements.
162b11c1e72Sjeremylt   @param r          Address of the variable where the newly created
163b11c1e72Sjeremylt                       CeedElemRestriction will be stored
164d7b241e6Sjeremylt 
165b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
166dfdf5a53Sjeremylt 
167dfdf5a53Sjeremylt   @ref Advanced
168b11c1e72Sjeremylt  **/
169d7b241e6Sjeremylt int CeedElemRestrictionCreateBlocked(Ceed ceed, CeedInt nelem, CeedInt elemsize,
170d7b241e6Sjeremylt                                      CeedInt blksize, CeedInt ndof, CeedInt ncomp,
171d7b241e6Sjeremylt                                      CeedMemType mtype, CeedCopyMode cmode,
172d7b241e6Sjeremylt                                      const CeedInt *indices, CeedElemRestriction *r) {
173d7b241e6Sjeremylt   int ierr;
174d7b241e6Sjeremylt   CeedInt *blkindices;
175d7b241e6Sjeremylt   CeedInt nblk = (nelem / blksize) + !!(nelem % blksize);
176d7b241e6Sjeremylt 
177d7b241e6Sjeremylt   if (!ceed->ElemRestrictionCreateBlocked)
178d7b241e6Sjeremylt     return CeedError(ceed, 1,
179d7b241e6Sjeremylt                      "Backend does not support ElemRestrictionCreateBlocked");
180d7b241e6Sjeremylt   if (mtype != CEED_MEM_HOST)
181d7b241e6Sjeremylt     return CeedError(ceed, 1, "Only MemType = HOST supported");
182d7b241e6Sjeremylt 
183d7b241e6Sjeremylt   ierr = CeedCalloc(1, r); CeedChk(ierr);
184d7b241e6Sjeremylt 
185d7b241e6Sjeremylt   if (indices) {
186d7b241e6Sjeremylt     ierr = CeedCalloc(nblk*blksize*elemsize, &blkindices);
187*4b8bea3bSJed Brown     ierr = CeedPermutePadIndices(indices, blkindices, nblk, nelem, blksize,
188*4b8bea3bSJed Brown                                  elemsize);
189dfdf5a53Sjeremylt     CeedChk(ierr);
190d7b241e6Sjeremylt   } else {
191d7b241e6Sjeremylt     blkindices = NULL;
192d7b241e6Sjeremylt   }
193d7b241e6Sjeremylt 
194d7b241e6Sjeremylt   (*r)->ceed = ceed;
195d7b241e6Sjeremylt   ceed->refcount++;
196d7b241e6Sjeremylt   (*r)->refcount = 1;
197d7b241e6Sjeremylt   (*r)->nelem = nelem;
198d7b241e6Sjeremylt   (*r)->elemsize = elemsize;
199d7b241e6Sjeremylt   (*r)->ndof = ndof;
200d7b241e6Sjeremylt   (*r)->ncomp = ncomp;
201d7b241e6Sjeremylt   (*r)->nblk = nblk;
202d7b241e6Sjeremylt   (*r)->blksize = blksize;
203d7b241e6Sjeremylt   ierr = ceed->ElemRestrictionCreateBlocked(*r, CEED_MEM_HOST, CEED_OWN_POINTER,
204d7b241e6Sjeremylt          (const CeedInt *) blkindices);
205d7b241e6Sjeremylt   CeedChk(ierr);
206d7b241e6Sjeremylt 
207d7b241e6Sjeremylt   if (cmode == CEED_OWN_POINTER)
208d7b241e6Sjeremylt     ierr = CeedFree(&indices); CeedChk(ierr);
209d7b241e6Sjeremylt 
210d7b241e6Sjeremylt   return 0;
211d7b241e6Sjeremylt }
212d7b241e6Sjeremylt 
213b11c1e72Sjeremylt /**
214b11c1e72Sjeremylt   @brief Create CeedVectors associated with a CeedElemRestriction
215b11c1e72Sjeremylt 
216b11c1e72Sjeremylt   @param r     CeedElemRestriction
217b11c1e72Sjeremylt   @param lvec  The address of the L-vector to be created, or NULL
218b11c1e72Sjeremylt   @param evec  The address of the E-vector to be created, or NULL
219b11c1e72Sjeremylt 
220b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
221dfdf5a53Sjeremylt 
222dfdf5a53Sjeremylt   @ref Advanced
223b11c1e72Sjeremylt **/
224d7b241e6Sjeremylt int CeedElemRestrictionCreateVector(CeedElemRestriction r, CeedVector *lvec,
225d7b241e6Sjeremylt                                     CeedVector *evec) {
226d7b241e6Sjeremylt   int ierr;
227d7b241e6Sjeremylt   CeedInt n, m;
228d7b241e6Sjeremylt   m = r->ndof * r->ncomp;
229d7b241e6Sjeremylt   n = r->nblk * r->blksize * r->elemsize * r->ncomp;
230d7b241e6Sjeremylt   if (lvec) {
231d7b241e6Sjeremylt     ierr = CeedVectorCreate(r->ceed, m, lvec); CeedChk(ierr);
232d7b241e6Sjeremylt   }
233d7b241e6Sjeremylt   if (evec) {
234d7b241e6Sjeremylt     ierr = CeedVectorCreate(r->ceed, n, evec); CeedChk(ierr);
235d7b241e6Sjeremylt   }
236d7b241e6Sjeremylt   return 0;
237d7b241e6Sjeremylt }
238d7b241e6Sjeremylt 
239d7b241e6Sjeremylt /**
240b11c1e72Sjeremylt   @brief Restrict an L-vector to an E-vector or apply transpose
241d7b241e6Sjeremylt 
242b11c1e72Sjeremylt   @param r       CeedElemRestriction
243d7b241e6Sjeremylt   @param tmode   Apply restriction or transpose
244d7b241e6Sjeremylt   @param lmode   Ordering of the ncomp components
245d7b241e6Sjeremylt   @param u       Input vector (of size @a ndof when tmode=CEED_NOTRANSPOSE)
246d7b241e6Sjeremylt   @param v       Output vector (of size @a nelem * @a elemsize when tmode=CEED_NOTRANSPOSE)
247d7b241e6Sjeremylt   @param request Request or CEED_REQUEST_IMMEDIATE
248b11c1e72Sjeremylt 
249b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
250dfdf5a53Sjeremylt 
251dfdf5a53Sjeremylt   @ref Advanced
252b11c1e72Sjeremylt **/
253d7b241e6Sjeremylt int CeedElemRestrictionApply(CeedElemRestriction r, CeedTransposeMode tmode,
254d7b241e6Sjeremylt                              CeedTransposeMode lmode,
255d7b241e6Sjeremylt                              CeedVector u, CeedVector v, CeedRequest *request) {
256d7b241e6Sjeremylt   CeedInt m,n;
257d7b241e6Sjeremylt   int ierr;
258d7b241e6Sjeremylt 
259d7b241e6Sjeremylt   if (tmode == CEED_NOTRANSPOSE) {
260d7b241e6Sjeremylt     m = r->nblk * r->blksize * r->elemsize * r->ncomp;
261d7b241e6Sjeremylt     n = r->ndof * r->ncomp;
262d7b241e6Sjeremylt   } else {
263d7b241e6Sjeremylt     m = r->ndof * r->ncomp;
264d7b241e6Sjeremylt     n = r->nblk * r->blksize * r->elemsize * r->ncomp;
265d7b241e6Sjeremylt   }
266d7b241e6Sjeremylt   if (n != u->length)
267d7b241e6Sjeremylt     return CeedError(r->ceed, 2,
268d7b241e6Sjeremylt                      "Input vector size %d not compatible with element restriction (%d, %d)",
269d7b241e6Sjeremylt                      u->length, m, n);
270d7b241e6Sjeremylt   if (m != v->length)
271d7b241e6Sjeremylt     return CeedError(r->ceed, 2,
272d7b241e6Sjeremylt                      "Output vector size %d not compatible with element restriction (%d, %d)",
273d7b241e6Sjeremylt                      v->length, m, n);
274d7b241e6Sjeremylt   ierr = r->Apply(r, tmode, lmode, u, v, request); CeedChk(ierr);
275d7b241e6Sjeremylt 
276d7b241e6Sjeremylt   return 0;
277d7b241e6Sjeremylt }
278d7b241e6Sjeremylt 
279d7b241e6Sjeremylt /**
280b11c1e72Sjeremylt   @brief Get the total number of elements in the range of a CeedElemRestriction
281d7b241e6Sjeremylt 
282b11c1e72Sjeremylt   @param r                CeedElemRestriction
283b11c1e72Sjeremylt   @param[out] numelements Number of elements
284b11c1e72Sjeremylt 
285b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
286dfdf5a53Sjeremylt 
287dfdf5a53Sjeremylt   @ref Utility
288b11c1e72Sjeremylt **/
289d7b241e6Sjeremylt int CeedElemRestrictionGetNumElements(CeedElemRestriction r,
290d7b241e6Sjeremylt                                       CeedInt *numelements) {
291d7b241e6Sjeremylt   *numelements = r->nelem;
292d7b241e6Sjeremylt   return 0;
293d7b241e6Sjeremylt }
294d7b241e6Sjeremylt 
295d7b241e6Sjeremylt /**
296b11c1e72Sjeremylt   @brief Destroy a CeedElemRestriction
297b11c1e72Sjeremylt 
298b11c1e72Sjeremylt   @param r CeedElemRestriction to destroy
299b11c1e72Sjeremylt 
300b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
301dfdf5a53Sjeremylt 
302dfdf5a53Sjeremylt   @ref Basic
303b11c1e72Sjeremylt **/
304d7b241e6Sjeremylt int CeedElemRestrictionDestroy(CeedElemRestriction *r) {
305d7b241e6Sjeremylt   int ierr;
306d7b241e6Sjeremylt 
307d7b241e6Sjeremylt   if (!*r || --(*r)->refcount > 0) return 0;
308d7b241e6Sjeremylt   if ((*r)->Destroy) {
309d7b241e6Sjeremylt     ierr = (*r)->Destroy(*r); CeedChk(ierr);
310d7b241e6Sjeremylt   }
311d7b241e6Sjeremylt   ierr = CeedDestroy(&(*r)->ceed); CeedChk(ierr);
312d7b241e6Sjeremylt   ierr = CeedFree(r); CeedChk(ierr);
313d7b241e6Sjeremylt   return 0;
314d7b241e6Sjeremylt }
315d7b241e6Sjeremylt 
316d7b241e6Sjeremylt /// @}
317