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