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