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