xref: /libCEED/rust/libceed/src/elem_restriction.rs (revision 9df49d7ef0a77c7a3baec2427d8a7274681409b6)
1*9df49d7eSJed Brown // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2*9df49d7eSJed Brown // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3*9df49d7eSJed Brown // reserved. See files LICENSE and NOTICE for details.
4*9df49d7eSJed Brown //
5*9df49d7eSJed Brown // This file is part of CEED, a collection of benchmarks, miniapps, software
6*9df49d7eSJed Brown // libraries and APIs for efficient high-order finite element and spectral
7*9df49d7eSJed Brown // element discretizations for exascale applications. For more information and
8*9df49d7eSJed Brown // source code availability see http://github.com/ceed.
9*9df49d7eSJed Brown //
10*9df49d7eSJed Brown // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11*9df49d7eSJed Brown // a collaborative effort of two U.S. Department of Energy organizations (Office
12*9df49d7eSJed Brown // of Science and the National Nuclear Security Administration) responsible for
13*9df49d7eSJed Brown // the planning and preparation of a capable exascale ecosystem, including
14*9df49d7eSJed Brown // software, applications, hardware, advanced system engineering and early
15*9df49d7eSJed Brown // testbed platforms, in support of the nation's exascale computing imperative
16*9df49d7eSJed Brown 
17*9df49d7eSJed Brown //! A Ceed ElemRestriction decomposes elements and groups the degrees of freedom
18*9df49d7eSJed Brown //! (dofs) according to the different elements they belong to.
19*9df49d7eSJed Brown 
20*9df49d7eSJed Brown use crate::prelude::*;
21*9df49d7eSJed Brown 
22*9df49d7eSJed Brown // -----------------------------------------------------------------------------
23*9df49d7eSJed Brown // CeedElemRestriction option
24*9df49d7eSJed Brown // -----------------------------------------------------------------------------
25*9df49d7eSJed Brown #[derive(Clone, Copy)]
26*9df49d7eSJed Brown pub enum ElemRestrictionOpt<'a> {
27*9df49d7eSJed Brown     Some(&'a ElemRestriction<'a>),
28*9df49d7eSJed Brown     None,
29*9df49d7eSJed Brown }
30*9df49d7eSJed Brown /// Construct a ElemRestrictionOpt reference from a ElemRestriction reference
31*9df49d7eSJed Brown impl<'a> From<&'a ElemRestriction<'_>> for ElemRestrictionOpt<'a> {
32*9df49d7eSJed Brown     fn from(restr: &'a ElemRestriction) -> Self {
33*9df49d7eSJed Brown         debug_assert!(restr.ptr != unsafe { bind_ceed::CEED_ELEMRESTRICTION_NONE });
34*9df49d7eSJed Brown         Self::Some(restr)
35*9df49d7eSJed Brown     }
36*9df49d7eSJed Brown }
37*9df49d7eSJed Brown impl<'a> ElemRestrictionOpt<'a> {
38*9df49d7eSJed Brown     /// Transform a Rust libCEED ElemRestrictionOpt into C libCEED
39*9df49d7eSJed Brown     /// CeedElemRestriction
40*9df49d7eSJed Brown     pub(crate) fn to_raw(self) -> bind_ceed::CeedElemRestriction {
41*9df49d7eSJed Brown         match self {
42*9df49d7eSJed Brown             Self::Some(restr) => restr.ptr,
43*9df49d7eSJed Brown             Self::None => unsafe { bind_ceed::CEED_ELEMRESTRICTION_NONE },
44*9df49d7eSJed Brown         }
45*9df49d7eSJed Brown     }
46*9df49d7eSJed Brown }
47*9df49d7eSJed Brown 
48*9df49d7eSJed Brown // -----------------------------------------------------------------------------
49*9df49d7eSJed Brown // CeedElemRestriction context wrapper
50*9df49d7eSJed Brown // -----------------------------------------------------------------------------
51*9df49d7eSJed Brown pub struct ElemRestriction<'a> {
52*9df49d7eSJed Brown     ceed: &'a crate::Ceed,
53*9df49d7eSJed Brown     pub(crate) ptr: bind_ceed::CeedElemRestriction,
54*9df49d7eSJed Brown }
55*9df49d7eSJed Brown 
56*9df49d7eSJed Brown // -----------------------------------------------------------------------------
57*9df49d7eSJed Brown // Destructor
58*9df49d7eSJed Brown // -----------------------------------------------------------------------------
59*9df49d7eSJed Brown impl<'a> Drop for ElemRestriction<'a> {
60*9df49d7eSJed Brown     fn drop(&mut self) {
61*9df49d7eSJed Brown         unsafe {
62*9df49d7eSJed Brown             if self.ptr != bind_ceed::CEED_ELEMRESTRICTION_NONE {
63*9df49d7eSJed Brown                 bind_ceed::CeedElemRestrictionDestroy(&mut self.ptr);
64*9df49d7eSJed Brown             }
65*9df49d7eSJed Brown         }
66*9df49d7eSJed Brown     }
67*9df49d7eSJed Brown }
68*9df49d7eSJed Brown 
69*9df49d7eSJed Brown // -----------------------------------------------------------------------------
70*9df49d7eSJed Brown // Display
71*9df49d7eSJed Brown // -----------------------------------------------------------------------------
72*9df49d7eSJed Brown impl<'a> fmt::Display for ElemRestriction<'a> {
73*9df49d7eSJed Brown     /// View an ElemRestriction
74*9df49d7eSJed Brown     ///
75*9df49d7eSJed Brown     /// ```
76*9df49d7eSJed Brown     /// # use libceed::prelude::*;
77*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
78*9df49d7eSJed Brown     /// let nelem = 3;
79*9df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
80*9df49d7eSJed Brown     /// for i in 0..nelem {
81*9df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
82*9df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
83*9df49d7eSJed Brown     /// }
84*9df49d7eSJed Brown     /// let r = ceed
85*9df49d7eSJed Brown     ///     .elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)
86*9df49d7eSJed Brown     ///     .unwrap();
87*9df49d7eSJed Brown     /// println!("{}", r);
88*9df49d7eSJed Brown     /// ```
89*9df49d7eSJed Brown     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90*9df49d7eSJed Brown         let mut ptr = std::ptr::null_mut();
91*9df49d7eSJed Brown         let mut sizeloc = crate::MAX_BUFFER_LENGTH;
92*9df49d7eSJed Brown         let cstring = unsafe {
93*9df49d7eSJed Brown             let file = bind_ceed::open_memstream(&mut ptr, &mut sizeloc);
94*9df49d7eSJed Brown             bind_ceed::CeedElemRestrictionView(self.ptr, file);
95*9df49d7eSJed Brown             bind_ceed::fclose(file);
96*9df49d7eSJed Brown             CString::from_raw(ptr)
97*9df49d7eSJed Brown         };
98*9df49d7eSJed Brown         cstring.to_string_lossy().fmt(f)
99*9df49d7eSJed Brown     }
100*9df49d7eSJed Brown }
101*9df49d7eSJed Brown 
102*9df49d7eSJed Brown // -----------------------------------------------------------------------------
103*9df49d7eSJed Brown // Implementations
104*9df49d7eSJed Brown // -----------------------------------------------------------------------------
105*9df49d7eSJed Brown impl<'a> ElemRestriction<'a> {
106*9df49d7eSJed Brown     // Constructors
107*9df49d7eSJed Brown     pub fn create(
108*9df49d7eSJed Brown         ceed: &'a crate::Ceed,
109*9df49d7eSJed Brown         nelem: usize,
110*9df49d7eSJed Brown         elemsize: usize,
111*9df49d7eSJed Brown         ncomp: usize,
112*9df49d7eSJed Brown         compstride: usize,
113*9df49d7eSJed Brown         lsize: usize,
114*9df49d7eSJed Brown         mtype: crate::MemType,
115*9df49d7eSJed Brown         offsets: &[i32],
116*9df49d7eSJed Brown     ) -> crate::Result<Self> {
117*9df49d7eSJed Brown         let mut ptr = std::ptr::null_mut();
118*9df49d7eSJed Brown         let (nelem, elemsize, ncomp, compstride, lsize, mtype) = (
119*9df49d7eSJed Brown             i32::try_from(nelem).unwrap(),
120*9df49d7eSJed Brown             i32::try_from(elemsize).unwrap(),
121*9df49d7eSJed Brown             i32::try_from(ncomp).unwrap(),
122*9df49d7eSJed Brown             i32::try_from(compstride).unwrap(),
123*9df49d7eSJed Brown             i32::try_from(lsize).unwrap(),
124*9df49d7eSJed Brown             mtype as bind_ceed::CeedMemType,
125*9df49d7eSJed Brown         );
126*9df49d7eSJed Brown         let ierr = unsafe {
127*9df49d7eSJed Brown             bind_ceed::CeedElemRestrictionCreate(
128*9df49d7eSJed Brown                 ceed.ptr,
129*9df49d7eSJed Brown                 nelem,
130*9df49d7eSJed Brown                 elemsize,
131*9df49d7eSJed Brown                 ncomp,
132*9df49d7eSJed Brown                 compstride,
133*9df49d7eSJed Brown                 lsize,
134*9df49d7eSJed Brown                 mtype,
135*9df49d7eSJed Brown                 crate::CopyMode::CopyValues as bind_ceed::CeedCopyMode,
136*9df49d7eSJed Brown                 offsets.as_ptr(),
137*9df49d7eSJed Brown                 &mut ptr,
138*9df49d7eSJed Brown             )
139*9df49d7eSJed Brown         };
140*9df49d7eSJed Brown         ceed.check_error(ierr)?;
141*9df49d7eSJed Brown         Ok(Self { ceed, ptr })
142*9df49d7eSJed Brown     }
143*9df49d7eSJed Brown 
144*9df49d7eSJed Brown     pub fn create_strided(
145*9df49d7eSJed Brown         ceed: &'a crate::Ceed,
146*9df49d7eSJed Brown         nelem: usize,
147*9df49d7eSJed Brown         elemsize: usize,
148*9df49d7eSJed Brown         ncomp: usize,
149*9df49d7eSJed Brown         lsize: usize,
150*9df49d7eSJed Brown         strides: [i32; 3],
151*9df49d7eSJed Brown     ) -> crate::Result<Self> {
152*9df49d7eSJed Brown         let mut ptr = std::ptr::null_mut();
153*9df49d7eSJed Brown         let (nelem, elemsize, ncomp, lsize) = (
154*9df49d7eSJed Brown             i32::try_from(nelem).unwrap(),
155*9df49d7eSJed Brown             i32::try_from(elemsize).unwrap(),
156*9df49d7eSJed Brown             i32::try_from(ncomp).unwrap(),
157*9df49d7eSJed Brown             i32::try_from(lsize).unwrap(),
158*9df49d7eSJed Brown         );
159*9df49d7eSJed Brown         let ierr = unsafe {
160*9df49d7eSJed Brown             bind_ceed::CeedElemRestrictionCreateStrided(
161*9df49d7eSJed Brown                 ceed.ptr,
162*9df49d7eSJed Brown                 nelem,
163*9df49d7eSJed Brown                 elemsize,
164*9df49d7eSJed Brown                 ncomp,
165*9df49d7eSJed Brown                 lsize,
166*9df49d7eSJed Brown                 strides.as_ptr(),
167*9df49d7eSJed Brown                 &mut ptr,
168*9df49d7eSJed Brown             )
169*9df49d7eSJed Brown         };
170*9df49d7eSJed Brown         ceed.check_error(ierr)?;
171*9df49d7eSJed Brown         Ok(Self { ceed, ptr })
172*9df49d7eSJed Brown     }
173*9df49d7eSJed Brown 
174*9df49d7eSJed Brown     /// Create an Lvector for an ElemRestriction
175*9df49d7eSJed Brown     ///
176*9df49d7eSJed Brown     /// ```
177*9df49d7eSJed Brown     /// # use libceed::prelude::*;
178*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
179*9df49d7eSJed Brown     /// let nelem = 3;
180*9df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
181*9df49d7eSJed Brown     /// for i in 0..nelem {
182*9df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
183*9df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
184*9df49d7eSJed Brown     /// }
185*9df49d7eSJed Brown     /// let r = ceed
186*9df49d7eSJed Brown     ///     .elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)
187*9df49d7eSJed Brown     ///     .unwrap();
188*9df49d7eSJed Brown     ///
189*9df49d7eSJed Brown     /// let lvector = r.create_lvector().unwrap();
190*9df49d7eSJed Brown     ///
191*9df49d7eSJed Brown     /// assert_eq!(lvector.length(), nelem + 1, "Incorrect Lvector size");
192*9df49d7eSJed Brown     /// ```
193*9df49d7eSJed Brown     pub fn create_lvector(&self) -> crate::Result<Vector> {
194*9df49d7eSJed Brown         let mut ptr_lvector = std::ptr::null_mut();
195*9df49d7eSJed Brown         let null = std::ptr::null_mut() as *mut _;
196*9df49d7eSJed Brown         let ierr =
197*9df49d7eSJed Brown             unsafe { bind_ceed::CeedElemRestrictionCreateVector(self.ptr, &mut ptr_lvector, null) };
198*9df49d7eSJed Brown         self.ceed.check_error(ierr)?;
199*9df49d7eSJed Brown         Vector::from_raw(self.ceed, ptr_lvector)
200*9df49d7eSJed Brown     }
201*9df49d7eSJed Brown 
202*9df49d7eSJed Brown     /// Create an Evector for an ElemRestriction
203*9df49d7eSJed Brown     ///
204*9df49d7eSJed Brown     /// ```
205*9df49d7eSJed Brown     /// # use libceed::prelude::*;
206*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
207*9df49d7eSJed Brown     /// let nelem = 3;
208*9df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
209*9df49d7eSJed Brown     /// for i in 0..nelem {
210*9df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
211*9df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
212*9df49d7eSJed Brown     /// }
213*9df49d7eSJed Brown     /// let r = ceed
214*9df49d7eSJed Brown     ///     .elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)
215*9df49d7eSJed Brown     ///     .unwrap();
216*9df49d7eSJed Brown     ///
217*9df49d7eSJed Brown     /// let evector = r.create_evector().unwrap();
218*9df49d7eSJed Brown     ///
219*9df49d7eSJed Brown     /// assert_eq!(evector.length(), nelem * 2, "Incorrect Evector size");
220*9df49d7eSJed Brown     /// ```
221*9df49d7eSJed Brown     pub fn create_evector(&self) -> crate::Result<Vector> {
222*9df49d7eSJed Brown         let mut ptr_evector = std::ptr::null_mut();
223*9df49d7eSJed Brown         let null = std::ptr::null_mut() as *mut _;
224*9df49d7eSJed Brown         let ierr =
225*9df49d7eSJed Brown             unsafe { bind_ceed::CeedElemRestrictionCreateVector(self.ptr, null, &mut ptr_evector) };
226*9df49d7eSJed Brown         self.ceed.check_error(ierr)?;
227*9df49d7eSJed Brown         Vector::from_raw(self.ceed, ptr_evector)
228*9df49d7eSJed Brown     }
229*9df49d7eSJed Brown 
230*9df49d7eSJed Brown     /// Create Vectors for an ElemRestriction
231*9df49d7eSJed Brown     ///
232*9df49d7eSJed Brown     /// ```
233*9df49d7eSJed Brown     /// # use libceed::prelude::*;
234*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
235*9df49d7eSJed Brown     /// let nelem = 3;
236*9df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
237*9df49d7eSJed Brown     /// for i in 0..nelem {
238*9df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
239*9df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
240*9df49d7eSJed Brown     /// }
241*9df49d7eSJed Brown     /// let r = ceed
242*9df49d7eSJed Brown     ///     .elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)
243*9df49d7eSJed Brown     ///     .unwrap();
244*9df49d7eSJed Brown     ///
245*9df49d7eSJed Brown     /// let (lvector, evector) = r.create_vectors().unwrap();
246*9df49d7eSJed Brown     ///
247*9df49d7eSJed Brown     /// assert_eq!(lvector.length(), nelem + 1, "Incorrect Lvector size");
248*9df49d7eSJed Brown     /// assert_eq!(evector.length(), nelem * 2, "Incorrect Evector size");
249*9df49d7eSJed Brown     /// ```
250*9df49d7eSJed Brown     pub fn create_vectors(&self) -> crate::Result<(Vector, Vector)> {
251*9df49d7eSJed Brown         let mut ptr_lvector = std::ptr::null_mut();
252*9df49d7eSJed Brown         let mut ptr_evector = std::ptr::null_mut();
253*9df49d7eSJed Brown         let ierr = unsafe {
254*9df49d7eSJed Brown             bind_ceed::CeedElemRestrictionCreateVector(self.ptr, &mut ptr_lvector, &mut ptr_evector)
255*9df49d7eSJed Brown         };
256*9df49d7eSJed Brown         self.ceed.check_error(ierr)?;
257*9df49d7eSJed Brown         let lvector = Vector::from_raw(self.ceed, ptr_lvector)?;
258*9df49d7eSJed Brown         let evector = Vector::from_raw(self.ceed, ptr_evector)?;
259*9df49d7eSJed Brown         Ok((lvector, evector))
260*9df49d7eSJed Brown     }
261*9df49d7eSJed Brown 
262*9df49d7eSJed Brown     /// Restrict an Lvector to an Evector or apply its transpose
263*9df49d7eSJed Brown     ///
264*9df49d7eSJed Brown     /// # arguments
265*9df49d7eSJed Brown     ///
266*9df49d7eSJed Brown     /// * `tmode` - Apply restriction or transpose
267*9df49d7eSJed Brown     /// * `u`     - Input vector (of size `lsize` when `TransposeMode::NoTranspose`)
268*9df49d7eSJed Brown     /// * `ru`    - Output vector (of shape `[nelem * elemsize]` when
269*9df49d7eSJed Brown     ///               `TransposeMode::NoTranspose`). Ordering of the Evector is
270*9df49d7eSJed Brown     ///               decided by the backend.
271*9df49d7eSJed Brown     ///
272*9df49d7eSJed Brown     /// ```
273*9df49d7eSJed Brown     /// # use libceed::prelude::*;
274*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
275*9df49d7eSJed Brown     /// let nelem = 3;
276*9df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
277*9df49d7eSJed Brown     /// for i in 0..nelem {
278*9df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
279*9df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
280*9df49d7eSJed Brown     /// }
281*9df49d7eSJed Brown     /// let r = ceed
282*9df49d7eSJed Brown     ///     .elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)
283*9df49d7eSJed Brown     ///     .unwrap();
284*9df49d7eSJed Brown     ///
285*9df49d7eSJed Brown     /// let x = ceed.vector_from_slice(&[0., 1., 2., 3.]).unwrap();
286*9df49d7eSJed Brown     /// let mut y = ceed.vector(nelem * 2).unwrap();
287*9df49d7eSJed Brown     /// y.set_value(0.0);
288*9df49d7eSJed Brown     ///
289*9df49d7eSJed Brown     /// r.apply(TransposeMode::NoTranspose, &x, &mut y).unwrap();
290*9df49d7eSJed Brown     ///
291*9df49d7eSJed Brown     /// y.view().iter().enumerate().for_each(|(i, arr)| {
292*9df49d7eSJed Brown     ///     assert_eq!(
293*9df49d7eSJed Brown     ///         *arr,
294*9df49d7eSJed Brown     ///         ((i + 1) / 2) as f64,
295*9df49d7eSJed Brown     ///         "Incorrect value in restricted vector"
296*9df49d7eSJed Brown     ///     );
297*9df49d7eSJed Brown     /// });
298*9df49d7eSJed Brown     /// ```
299*9df49d7eSJed Brown     pub fn apply(&self, tmode: TransposeMode, u: &Vector, ru: &mut Vector) -> crate::Result<i32> {
300*9df49d7eSJed Brown         let tmode = tmode as bind_ceed::CeedTransposeMode;
301*9df49d7eSJed Brown         let ierr = unsafe {
302*9df49d7eSJed Brown             bind_ceed::CeedElemRestrictionApply(
303*9df49d7eSJed Brown                 self.ptr,
304*9df49d7eSJed Brown                 tmode,
305*9df49d7eSJed Brown                 u.ptr,
306*9df49d7eSJed Brown                 ru.ptr,
307*9df49d7eSJed Brown                 bind_ceed::CEED_REQUEST_IMMEDIATE,
308*9df49d7eSJed Brown             )
309*9df49d7eSJed Brown         };
310*9df49d7eSJed Brown         self.ceed.check_error(ierr)
311*9df49d7eSJed Brown     }
312*9df49d7eSJed Brown 
313*9df49d7eSJed Brown     /// Returns the Lvector component stride
314*9df49d7eSJed Brown     ///
315*9df49d7eSJed Brown     /// ```
316*9df49d7eSJed Brown     /// # use libceed::prelude::*;
317*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
318*9df49d7eSJed Brown     /// let nelem = 3;
319*9df49d7eSJed Brown     /// let compstride = 1;
320*9df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
321*9df49d7eSJed Brown     /// for i in 0..nelem {
322*9df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
323*9df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
324*9df49d7eSJed Brown     /// }
325*9df49d7eSJed Brown     /// let r = ceed
326*9df49d7eSJed Brown     ///     .elem_restriction(nelem, 2, 1, compstride, nelem + 1, MemType::Host, &ind)
327*9df49d7eSJed Brown     ///     .unwrap();
328*9df49d7eSJed Brown     ///
329*9df49d7eSJed Brown     /// let c = r.comp_stride();
330*9df49d7eSJed Brown     /// assert_eq!(c, compstride, "Incorrect component stride");
331*9df49d7eSJed Brown     /// ```
332*9df49d7eSJed Brown     pub fn comp_stride(&self) -> usize {
333*9df49d7eSJed Brown         let mut compstride = 0;
334*9df49d7eSJed Brown         unsafe { bind_ceed::CeedElemRestrictionGetCompStride(self.ptr, &mut compstride) };
335*9df49d7eSJed Brown         usize::try_from(compstride).unwrap()
336*9df49d7eSJed Brown     }
337*9df49d7eSJed Brown 
338*9df49d7eSJed Brown     /// Returns the total number of elements in the range of a ElemRestriction
339*9df49d7eSJed Brown     ///
340*9df49d7eSJed Brown     /// ```
341*9df49d7eSJed Brown     /// # use libceed::prelude::*;
342*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
343*9df49d7eSJed Brown     /// let nelem = 3;
344*9df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
345*9df49d7eSJed Brown     /// for i in 0..nelem {
346*9df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
347*9df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
348*9df49d7eSJed Brown     /// }
349*9df49d7eSJed Brown     /// let r = ceed
350*9df49d7eSJed Brown     ///     .elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)
351*9df49d7eSJed Brown     ///     .unwrap();
352*9df49d7eSJed Brown     ///
353*9df49d7eSJed Brown     /// let n = r.num_elements();
354*9df49d7eSJed Brown     /// assert_eq!(n, nelem, "Incorrect number of elements");
355*9df49d7eSJed Brown     /// ```
356*9df49d7eSJed Brown     pub fn num_elements(&self) -> usize {
357*9df49d7eSJed Brown         let mut numelem = 0;
358*9df49d7eSJed Brown         unsafe { bind_ceed::CeedElemRestrictionGetNumElements(self.ptr, &mut numelem) };
359*9df49d7eSJed Brown         usize::try_from(numelem).unwrap()
360*9df49d7eSJed Brown     }
361*9df49d7eSJed Brown 
362*9df49d7eSJed Brown     /// Returns the size of elements in the ElemRestriction
363*9df49d7eSJed Brown     ///
364*9df49d7eSJed Brown     /// ```
365*9df49d7eSJed Brown     /// # use libceed::prelude::*;
366*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
367*9df49d7eSJed Brown     /// let nelem = 3;
368*9df49d7eSJed Brown     /// let elem_size = 2;
369*9df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
370*9df49d7eSJed Brown     /// for i in 0..nelem {
371*9df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
372*9df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
373*9df49d7eSJed Brown     /// }
374*9df49d7eSJed Brown     /// let r = ceed
375*9df49d7eSJed Brown     ///     .elem_restriction(nelem, elem_size, 1, 1, nelem + 1, MemType::Host, &ind)
376*9df49d7eSJed Brown     ///     .unwrap();
377*9df49d7eSJed Brown     ///
378*9df49d7eSJed Brown     /// let e = r.elem_size();
379*9df49d7eSJed Brown     /// assert_eq!(e, elem_size, "Incorrect element size");
380*9df49d7eSJed Brown     /// ```
381*9df49d7eSJed Brown     pub fn elem_size(&self) -> usize {
382*9df49d7eSJed Brown         let mut elemsize = 0;
383*9df49d7eSJed Brown         unsafe { bind_ceed::CeedElemRestrictionGetElementSize(self.ptr, &mut elemsize) };
384*9df49d7eSJed Brown         usize::try_from(elemsize).unwrap()
385*9df49d7eSJed Brown     }
386*9df49d7eSJed Brown 
387*9df49d7eSJed Brown     /// Returns the size of the Lvector for an ElemRestriction
388*9df49d7eSJed Brown     ///
389*9df49d7eSJed Brown     /// ```
390*9df49d7eSJed Brown     /// # use libceed::prelude::*;
391*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
392*9df49d7eSJed Brown     /// let nelem = 3;
393*9df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
394*9df49d7eSJed Brown     /// for i in 0..nelem {
395*9df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
396*9df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
397*9df49d7eSJed Brown     /// }
398*9df49d7eSJed Brown     /// let r = ceed
399*9df49d7eSJed Brown     ///     .elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)
400*9df49d7eSJed Brown     ///     .unwrap();
401*9df49d7eSJed Brown     ///
402*9df49d7eSJed Brown     /// let lsize = r.lvector_size();
403*9df49d7eSJed Brown     /// assert_eq!(lsize, nelem + 1);
404*9df49d7eSJed Brown     /// ```
405*9df49d7eSJed Brown     pub fn lvector_size(&self) -> usize {
406*9df49d7eSJed Brown         let mut lsize = 0;
407*9df49d7eSJed Brown         unsafe { bind_ceed::CeedElemRestrictionGetLVectorSize(self.ptr, &mut lsize) };
408*9df49d7eSJed Brown         usize::try_from(lsize).unwrap()
409*9df49d7eSJed Brown     }
410*9df49d7eSJed Brown 
411*9df49d7eSJed Brown     /// Returns the number of components in the elements of an ElemRestriction
412*9df49d7eSJed Brown     ///
413*9df49d7eSJed Brown     /// ```
414*9df49d7eSJed Brown     /// # use libceed::prelude::*;
415*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
416*9df49d7eSJed Brown     /// let nelem = 3;
417*9df49d7eSJed Brown     /// let ncomp = 42;
418*9df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
419*9df49d7eSJed Brown     /// for i in 0..nelem {
420*9df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
421*9df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
422*9df49d7eSJed Brown     /// }
423*9df49d7eSJed Brown     /// let r = ceed
424*9df49d7eSJed Brown     ///     .elem_restriction(nelem, 2, 42, 1, ncomp * (nelem + 1), MemType::Host, &ind)
425*9df49d7eSJed Brown     ///     .unwrap();
426*9df49d7eSJed Brown     ///
427*9df49d7eSJed Brown     /// let n = r.num_components();
428*9df49d7eSJed Brown     /// assert_eq!(n, ncomp, "Incorrect number of components");
429*9df49d7eSJed Brown     /// ```
430*9df49d7eSJed Brown     pub fn num_components(&self) -> usize {
431*9df49d7eSJed Brown         let mut ncomp = 0;
432*9df49d7eSJed Brown         unsafe { bind_ceed::CeedElemRestrictionGetNumComponents(self.ptr, &mut ncomp) };
433*9df49d7eSJed Brown         usize::try_from(ncomp).unwrap()
434*9df49d7eSJed Brown     }
435*9df49d7eSJed Brown 
436*9df49d7eSJed Brown     /// Returns the multiplicity of nodes in an ElemRestriction
437*9df49d7eSJed Brown     ///
438*9df49d7eSJed Brown     /// ```
439*9df49d7eSJed Brown     /// # use libceed::prelude::*;
440*9df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
441*9df49d7eSJed Brown     /// let nelem = 3;
442*9df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
443*9df49d7eSJed Brown     /// for i in 0..nelem {
444*9df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
445*9df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
446*9df49d7eSJed Brown     /// }
447*9df49d7eSJed Brown     /// let r = ceed
448*9df49d7eSJed Brown     ///     .elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)
449*9df49d7eSJed Brown     ///     .unwrap();
450*9df49d7eSJed Brown     ///
451*9df49d7eSJed Brown     /// let mut mult = ceed.vector(nelem + 1).unwrap();
452*9df49d7eSJed Brown     /// mult.set_value(0.0);
453*9df49d7eSJed Brown     ///
454*9df49d7eSJed Brown     /// r.multiplicity(&mut mult).unwrap();
455*9df49d7eSJed Brown     ///
456*9df49d7eSJed Brown     /// mult.view().iter().enumerate().for_each(|(i, arr)| {
457*9df49d7eSJed Brown     ///     assert_eq!(
458*9df49d7eSJed Brown     ///         if (i == 0 || i == nelem) { 1. } else { 2. },
459*9df49d7eSJed Brown     ///         *arr,
460*9df49d7eSJed Brown     ///         "Incorrect multiplicity array"
461*9df49d7eSJed Brown     ///     );
462*9df49d7eSJed Brown     /// });
463*9df49d7eSJed Brown     /// ```
464*9df49d7eSJed Brown     pub fn multiplicity(&self, mult: &mut Vector) -> crate::Result<i32> {
465*9df49d7eSJed Brown         let ierr = unsafe { bind_ceed::CeedElemRestrictionGetMultiplicity(self.ptr, mult.ptr) };
466*9df49d7eSJed Brown         self.ceed.check_error(ierr)
467*9df49d7eSJed Brown     }
468*9df49d7eSJed Brown }
469*9df49d7eSJed Brown 
470*9df49d7eSJed Brown // -----------------------------------------------------------------------------
471