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