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