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