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