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