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