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