xref: /libCEED/rust/libceed/src/elem_restriction.rs (revision e03682af89f4c0f5e8c281990d44146e81dbdd46)
19df49d7eSJed Brown // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
29df49d7eSJed Brown // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
39df49d7eSJed Brown // reserved. See files LICENSE and NOTICE for details.
49df49d7eSJed Brown //
59df49d7eSJed Brown // This file is part of CEED, a collection of benchmarks, miniapps, software
69df49d7eSJed Brown // libraries and APIs for efficient high-order finite element and spectral
79df49d7eSJed Brown // element discretizations for exascale applications. For more information and
89df49d7eSJed Brown // source code availability see http://github.com/ceed.
99df49d7eSJed Brown //
109df49d7eSJed Brown // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
119df49d7eSJed Brown // a collaborative effort of two U.S. Department of Energy organizations (Office
129df49d7eSJed Brown // of Science and the National Nuclear Security Administration) responsible for
139df49d7eSJed Brown // the planning and preparation of a capable exascale ecosystem, including
149df49d7eSJed Brown // software, applications, hardware, advanced system engineering and early
159df49d7eSJed Brown // testbed platforms, in support of the nation's exascale computing imperative
169df49d7eSJed Brown 
179df49d7eSJed Brown //! A Ceed ElemRestriction decomposes elements and groups the degrees of freedom
189df49d7eSJed Brown //! (dofs) according to the different elements they belong to.
199df49d7eSJed Brown 
209df49d7eSJed Brown use crate::prelude::*;
219df49d7eSJed Brown 
229df49d7eSJed Brown // -----------------------------------------------------------------------------
239df49d7eSJed Brown // CeedElemRestriction option
249df49d7eSJed Brown // -----------------------------------------------------------------------------
25c68be7a2SJeremy L Thompson #[derive(Debug)]
269df49d7eSJed Brown pub enum ElemRestrictionOpt<'a> {
279df49d7eSJed Brown     Some(&'a ElemRestriction<'a>),
289df49d7eSJed Brown     None,
299df49d7eSJed Brown }
309df49d7eSJed Brown /// Construct a ElemRestrictionOpt reference from a ElemRestriction reference
319df49d7eSJed Brown impl<'a> From<&'a ElemRestriction<'_>> for ElemRestrictionOpt<'a> {
329df49d7eSJed Brown     fn from(restr: &'a ElemRestriction) -> Self {
339df49d7eSJed Brown         debug_assert!(restr.ptr != unsafe { bind_ceed::CEED_ELEMRESTRICTION_NONE });
349df49d7eSJed Brown         Self::Some(restr)
359df49d7eSJed Brown     }
369df49d7eSJed Brown }
379df49d7eSJed Brown impl<'a> ElemRestrictionOpt<'a> {
389df49d7eSJed Brown     /// Transform a Rust libCEED ElemRestrictionOpt into C libCEED
399df49d7eSJed Brown     /// CeedElemRestriction
409df49d7eSJed Brown     pub(crate) fn to_raw(self) -> bind_ceed::CeedElemRestriction {
419df49d7eSJed Brown         match self {
429df49d7eSJed Brown             Self::Some(restr) => restr.ptr,
439df49d7eSJed Brown             Self::None => unsafe { bind_ceed::CEED_ELEMRESTRICTION_NONE },
449df49d7eSJed Brown         }
459df49d7eSJed Brown     }
46*e03682afSJeremy L Thompson 
47*e03682afSJeremy L Thompson     /// Check if an ElemRestrictionOpt is Some
48*e03682afSJeremy L Thompson     ///
49*e03682afSJeremy L Thompson     /// ```
50*e03682afSJeremy L Thompson     /// # use libceed::prelude::*;
51*e03682afSJeremy L Thompson     /// # fn main() -> Result<(), libceed::CeedError> {
52*e03682afSJeremy L Thompson     /// # let ceed = libceed::Ceed::default_init();
53*e03682afSJeremy L Thompson     /// let nelem = 3;
54*e03682afSJeremy L Thompson     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
55*e03682afSJeremy L Thompson     /// for i in 0..nelem {
56*e03682afSJeremy L Thompson     ///     ind[2 * i + 0] = i as i32;
57*e03682afSJeremy L Thompson     ///     ind[2 * i + 1] = (i + 1) as i32;
58*e03682afSJeremy L Thompson     /// }
59*e03682afSJeremy L Thompson     /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?;
60*e03682afSJeremy L Thompson     /// let r_opt = ElemRestrictionOpt::from(&r);
61*e03682afSJeremy L Thompson     /// assert!(r_opt.is_some(), "Incorrect ElemRestrictionOpt");
62*e03682afSJeremy L Thompson     ///
63*e03682afSJeremy L Thompson     /// let r_opt = ElemRestrictionOpt::None;
64*e03682afSJeremy L Thompson     /// assert!(!r_opt.is_some(), "Incorrect ElemRestrictionOpt");
65*e03682afSJeremy L Thompson     /// # Ok(())
66*e03682afSJeremy L Thompson     /// # }
67*e03682afSJeremy L Thompson     /// ```
68*e03682afSJeremy L Thompson     pub fn is_some(&self) -> bool {
69*e03682afSJeremy L Thompson         match self {
70*e03682afSJeremy L Thompson             Self::Some(_) => true,
71*e03682afSJeremy L Thompson             Self::None => false,
72*e03682afSJeremy L Thompson         }
73*e03682afSJeremy L Thompson     }
74*e03682afSJeremy L Thompson 
75*e03682afSJeremy L Thompson     /// Check if an ElemRestrictionOpt is None
76*e03682afSJeremy L Thompson     ///
77*e03682afSJeremy L Thompson     /// ```
78*e03682afSJeremy L Thompson     /// # use libceed::prelude::*;
79*e03682afSJeremy L Thompson     /// # fn main() -> Result<(), libceed::CeedError> {
80*e03682afSJeremy L Thompson     /// # let ceed = libceed::Ceed::default_init();
81*e03682afSJeremy L Thompson     /// let nelem = 3;
82*e03682afSJeremy L Thompson     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
83*e03682afSJeremy L Thompson     /// for i in 0..nelem {
84*e03682afSJeremy L Thompson     ///     ind[2 * i + 0] = i as i32;
85*e03682afSJeremy L Thompson     ///     ind[2 * i + 1] = (i + 1) as i32;
86*e03682afSJeremy L Thompson     /// }
87*e03682afSJeremy L Thompson     /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?;
88*e03682afSJeremy L Thompson     /// let r_opt = ElemRestrictionOpt::from(&r);
89*e03682afSJeremy L Thompson     /// assert!(!r_opt.is_none(), "Incorrect ElemRestrictionOpt");
90*e03682afSJeremy L Thompson     ///
91*e03682afSJeremy L Thompson     /// let r_opt = ElemRestrictionOpt::None;
92*e03682afSJeremy L Thompson     /// assert!(r_opt.is_none(), "Incorrect ElemRestrictionOpt");
93*e03682afSJeremy L Thompson     /// # Ok(())
94*e03682afSJeremy L Thompson     /// # }
95*e03682afSJeremy L Thompson     /// ```
96*e03682afSJeremy L Thompson     pub fn is_none(&self) -> bool {
97*e03682afSJeremy L Thompson         match self {
98*e03682afSJeremy L Thompson             Self::Some(_) => false,
99*e03682afSJeremy L Thompson             Self::None => true,
100*e03682afSJeremy L Thompson         }
101*e03682afSJeremy L Thompson     }
1029df49d7eSJed Brown }
1039df49d7eSJed Brown 
1049df49d7eSJed Brown // -----------------------------------------------------------------------------
1059df49d7eSJed Brown // CeedElemRestriction context wrapper
1069df49d7eSJed Brown // -----------------------------------------------------------------------------
107c68be7a2SJeremy L Thompson #[derive(Debug)]
1089df49d7eSJed Brown pub struct ElemRestriction<'a> {
1099df49d7eSJed Brown     ceed: &'a crate::Ceed,
1109df49d7eSJed Brown     pub(crate) ptr: bind_ceed::CeedElemRestriction,
1119df49d7eSJed Brown }
1129df49d7eSJed Brown 
1139df49d7eSJed Brown // -----------------------------------------------------------------------------
1149df49d7eSJed Brown // Destructor
1159df49d7eSJed Brown // -----------------------------------------------------------------------------
1169df49d7eSJed Brown impl<'a> Drop for ElemRestriction<'a> {
1179df49d7eSJed Brown     fn drop(&mut self) {
1189df49d7eSJed Brown         unsafe {
1199df49d7eSJed Brown             if self.ptr != bind_ceed::CEED_ELEMRESTRICTION_NONE {
1209df49d7eSJed Brown                 bind_ceed::CeedElemRestrictionDestroy(&mut self.ptr);
1219df49d7eSJed Brown             }
1229df49d7eSJed Brown         }
1239df49d7eSJed Brown     }
1249df49d7eSJed Brown }
1259df49d7eSJed Brown 
1269df49d7eSJed Brown // -----------------------------------------------------------------------------
1279df49d7eSJed Brown // Display
1289df49d7eSJed Brown // -----------------------------------------------------------------------------
1299df49d7eSJed Brown impl<'a> fmt::Display for ElemRestriction<'a> {
1309df49d7eSJed Brown     /// View an ElemRestriction
1319df49d7eSJed Brown     ///
1329df49d7eSJed Brown     /// ```
1339df49d7eSJed Brown     /// # use libceed::prelude::*;
134c68be7a2SJeremy L Thompson     /// # fn main() -> Result<(), libceed::CeedError> {
1359df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
1369df49d7eSJed Brown     /// let nelem = 3;
1379df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
1389df49d7eSJed Brown     /// for i in 0..nelem {
1399df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
1409df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
1419df49d7eSJed Brown     /// }
142c68be7a2SJeremy L Thompson     /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?;
1439df49d7eSJed Brown     /// println!("{}", r);
144c68be7a2SJeremy L Thompson     /// # Ok(())
145c68be7a2SJeremy L Thompson     /// # }
1469df49d7eSJed Brown     /// ```
1479df49d7eSJed Brown     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1489df49d7eSJed Brown         let mut ptr = std::ptr::null_mut();
1499df49d7eSJed Brown         let mut sizeloc = crate::MAX_BUFFER_LENGTH;
1509df49d7eSJed Brown         let cstring = unsafe {
1519df49d7eSJed Brown             let file = bind_ceed::open_memstream(&mut ptr, &mut sizeloc);
1529df49d7eSJed Brown             bind_ceed::CeedElemRestrictionView(self.ptr, file);
1539df49d7eSJed Brown             bind_ceed::fclose(file);
1549df49d7eSJed Brown             CString::from_raw(ptr)
1559df49d7eSJed Brown         };
1569df49d7eSJed Brown         cstring.to_string_lossy().fmt(f)
1579df49d7eSJed Brown     }
1589df49d7eSJed Brown }
1599df49d7eSJed Brown 
1609df49d7eSJed Brown // -----------------------------------------------------------------------------
1619df49d7eSJed Brown // Implementations
1629df49d7eSJed Brown // -----------------------------------------------------------------------------
1639df49d7eSJed Brown impl<'a> ElemRestriction<'a> {
1649df49d7eSJed Brown     // Constructors
1659df49d7eSJed Brown     pub fn create(
1669df49d7eSJed Brown         ceed: &'a crate::Ceed,
1679df49d7eSJed Brown         nelem: usize,
1689df49d7eSJed Brown         elemsize: usize,
1699df49d7eSJed Brown         ncomp: usize,
1709df49d7eSJed Brown         compstride: usize,
1719df49d7eSJed Brown         lsize: usize,
1729df49d7eSJed Brown         mtype: crate::MemType,
1739df49d7eSJed Brown         offsets: &[i32],
1749df49d7eSJed Brown     ) -> crate::Result<Self> {
1759df49d7eSJed Brown         let mut ptr = std::ptr::null_mut();
1769df49d7eSJed Brown         let (nelem, elemsize, ncomp, compstride, lsize, mtype) = (
1779df49d7eSJed Brown             i32::try_from(nelem).unwrap(),
1789df49d7eSJed Brown             i32::try_from(elemsize).unwrap(),
1799df49d7eSJed Brown             i32::try_from(ncomp).unwrap(),
1809df49d7eSJed Brown             i32::try_from(compstride).unwrap(),
1819df49d7eSJed Brown             i32::try_from(lsize).unwrap(),
1829df49d7eSJed Brown             mtype as bind_ceed::CeedMemType,
1839df49d7eSJed Brown         );
1849df49d7eSJed Brown         let ierr = unsafe {
1859df49d7eSJed Brown             bind_ceed::CeedElemRestrictionCreate(
1869df49d7eSJed Brown                 ceed.ptr,
1879df49d7eSJed Brown                 nelem,
1889df49d7eSJed Brown                 elemsize,
1899df49d7eSJed Brown                 ncomp,
1909df49d7eSJed Brown                 compstride,
1919df49d7eSJed Brown                 lsize,
1929df49d7eSJed Brown                 mtype,
1939df49d7eSJed Brown                 crate::CopyMode::CopyValues as bind_ceed::CeedCopyMode,
1949df49d7eSJed Brown                 offsets.as_ptr(),
1959df49d7eSJed Brown                 &mut ptr,
1969df49d7eSJed Brown             )
1979df49d7eSJed Brown         };
1989df49d7eSJed Brown         ceed.check_error(ierr)?;
1999df49d7eSJed Brown         Ok(Self { ceed, ptr })
2009df49d7eSJed Brown     }
2019df49d7eSJed Brown 
2029df49d7eSJed Brown     pub fn create_strided(
2039df49d7eSJed Brown         ceed: &'a crate::Ceed,
2049df49d7eSJed Brown         nelem: usize,
2059df49d7eSJed Brown         elemsize: usize,
2069df49d7eSJed Brown         ncomp: usize,
2079df49d7eSJed Brown         lsize: usize,
2089df49d7eSJed Brown         strides: [i32; 3],
2099df49d7eSJed Brown     ) -> crate::Result<Self> {
2109df49d7eSJed Brown         let mut ptr = std::ptr::null_mut();
2119df49d7eSJed Brown         let (nelem, elemsize, ncomp, lsize) = (
2129df49d7eSJed Brown             i32::try_from(nelem).unwrap(),
2139df49d7eSJed Brown             i32::try_from(elemsize).unwrap(),
2149df49d7eSJed Brown             i32::try_from(ncomp).unwrap(),
2159df49d7eSJed Brown             i32::try_from(lsize).unwrap(),
2169df49d7eSJed Brown         );
2179df49d7eSJed Brown         let ierr = unsafe {
2189df49d7eSJed Brown             bind_ceed::CeedElemRestrictionCreateStrided(
2199df49d7eSJed Brown                 ceed.ptr,
2209df49d7eSJed Brown                 nelem,
2219df49d7eSJed Brown                 elemsize,
2229df49d7eSJed Brown                 ncomp,
2239df49d7eSJed Brown                 lsize,
2249df49d7eSJed Brown                 strides.as_ptr(),
2259df49d7eSJed Brown                 &mut ptr,
2269df49d7eSJed Brown             )
2279df49d7eSJed Brown         };
2289df49d7eSJed Brown         ceed.check_error(ierr)?;
2299df49d7eSJed Brown         Ok(Self { ceed, ptr })
2309df49d7eSJed Brown     }
2319df49d7eSJed Brown 
2329df49d7eSJed Brown     /// Create an Lvector for an ElemRestriction
2339df49d7eSJed Brown     ///
2349df49d7eSJed Brown     /// ```
2359df49d7eSJed Brown     /// # use libceed::prelude::*;
236c68be7a2SJeremy L Thompson     /// # fn main() -> Result<(), libceed::CeedError> {
2379df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
2389df49d7eSJed Brown     /// let nelem = 3;
2399df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
2409df49d7eSJed Brown     /// for i in 0..nelem {
2419df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
2429df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
2439df49d7eSJed Brown     /// }
244c68be7a2SJeremy L Thompson     /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?;
2459df49d7eSJed Brown     ///
246c68be7a2SJeremy L Thompson     /// let lvector = r.create_lvector()?;
2479df49d7eSJed Brown     ///
2489df49d7eSJed Brown     /// assert_eq!(lvector.length(), nelem + 1, "Incorrect Lvector size");
249c68be7a2SJeremy L Thompson     /// # Ok(())
250c68be7a2SJeremy L Thompson     /// # }
2519df49d7eSJed Brown     /// ```
2529df49d7eSJed Brown     pub fn create_lvector(&self) -> crate::Result<Vector> {
2539df49d7eSJed Brown         let mut ptr_lvector = std::ptr::null_mut();
2549df49d7eSJed Brown         let null = std::ptr::null_mut() as *mut _;
2559df49d7eSJed Brown         let ierr =
2569df49d7eSJed Brown             unsafe { bind_ceed::CeedElemRestrictionCreateVector(self.ptr, &mut ptr_lvector, null) };
2579df49d7eSJed Brown         self.ceed.check_error(ierr)?;
2589df49d7eSJed Brown         Vector::from_raw(self.ceed, ptr_lvector)
2599df49d7eSJed Brown     }
2609df49d7eSJed Brown 
2619df49d7eSJed Brown     /// Create an Evector for an ElemRestriction
2629df49d7eSJed Brown     ///
2639df49d7eSJed Brown     /// ```
2649df49d7eSJed Brown     /// # use libceed::prelude::*;
265c68be7a2SJeremy L Thompson     /// # fn main() -> Result<(), libceed::CeedError> {
2669df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
2679df49d7eSJed Brown     /// let nelem = 3;
2689df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
2699df49d7eSJed Brown     /// for i in 0..nelem {
2709df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
2719df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
2729df49d7eSJed Brown     /// }
273c68be7a2SJeremy L Thompson     /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?;
2749df49d7eSJed Brown     ///
275c68be7a2SJeremy L Thompson     /// let evector = r.create_evector()?;
2769df49d7eSJed Brown     ///
2779df49d7eSJed Brown     /// assert_eq!(evector.length(), nelem * 2, "Incorrect Evector size");
278c68be7a2SJeremy L Thompson     /// # Ok(())
279c68be7a2SJeremy L Thompson     /// # }
2809df49d7eSJed Brown     /// ```
2819df49d7eSJed Brown     pub fn create_evector(&self) -> crate::Result<Vector> {
2829df49d7eSJed Brown         let mut ptr_evector = std::ptr::null_mut();
2839df49d7eSJed Brown         let null = std::ptr::null_mut() as *mut _;
2849df49d7eSJed Brown         let ierr =
2859df49d7eSJed Brown             unsafe { bind_ceed::CeedElemRestrictionCreateVector(self.ptr, null, &mut ptr_evector) };
2869df49d7eSJed Brown         self.ceed.check_error(ierr)?;
2879df49d7eSJed Brown         Vector::from_raw(self.ceed, ptr_evector)
2889df49d7eSJed Brown     }
2899df49d7eSJed Brown 
2909df49d7eSJed Brown     /// Create Vectors for an ElemRestriction
2919df49d7eSJed Brown     ///
2929df49d7eSJed Brown     /// ```
2939df49d7eSJed Brown     /// # use libceed::prelude::*;
294c68be7a2SJeremy L Thompson     /// # fn main() -> Result<(), libceed::CeedError> {
2959df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
2969df49d7eSJed Brown     /// let nelem = 3;
2979df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
2989df49d7eSJed Brown     /// for i in 0..nelem {
2999df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
3009df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
3019df49d7eSJed Brown     /// }
302c68be7a2SJeremy L Thompson     /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?;
3039df49d7eSJed Brown     ///
304c68be7a2SJeremy L Thompson     /// let (lvector, evector) = r.create_vectors()?;
3059df49d7eSJed Brown     ///
3069df49d7eSJed Brown     /// assert_eq!(lvector.length(), nelem + 1, "Incorrect Lvector size");
3079df49d7eSJed Brown     /// assert_eq!(evector.length(), nelem * 2, "Incorrect Evector size");
308c68be7a2SJeremy L Thompson     /// # Ok(())
309c68be7a2SJeremy L Thompson     /// # }
3109df49d7eSJed Brown     /// ```
3119df49d7eSJed Brown     pub fn create_vectors(&self) -> crate::Result<(Vector, Vector)> {
3129df49d7eSJed Brown         let mut ptr_lvector = std::ptr::null_mut();
3139df49d7eSJed Brown         let mut ptr_evector = std::ptr::null_mut();
3149df49d7eSJed Brown         let ierr = unsafe {
3159df49d7eSJed Brown             bind_ceed::CeedElemRestrictionCreateVector(self.ptr, &mut ptr_lvector, &mut ptr_evector)
3169df49d7eSJed Brown         };
3179df49d7eSJed Brown         self.ceed.check_error(ierr)?;
3189df49d7eSJed Brown         let lvector = Vector::from_raw(self.ceed, ptr_lvector)?;
3199df49d7eSJed Brown         let evector = Vector::from_raw(self.ceed, ptr_evector)?;
3209df49d7eSJed Brown         Ok((lvector, evector))
3219df49d7eSJed Brown     }
3229df49d7eSJed Brown 
3239df49d7eSJed Brown     /// Restrict an Lvector to an Evector or apply its transpose
3249df49d7eSJed Brown     ///
3259df49d7eSJed Brown     /// # arguments
3269df49d7eSJed Brown     ///
3279df49d7eSJed Brown     /// * `tmode` - Apply restriction or transpose
3289df49d7eSJed Brown     /// * `u`     - Input vector (of size `lsize` when `TransposeMode::NoTranspose`)
3299df49d7eSJed Brown     /// * `ru`    - Output vector (of shape `[nelem * elemsize]` when
3309df49d7eSJed Brown     ///               `TransposeMode::NoTranspose`). Ordering of the Evector is
3319df49d7eSJed Brown     ///               decided by the backend.
3329df49d7eSJed Brown     ///
3339df49d7eSJed Brown     /// ```
3349df49d7eSJed Brown     /// # use libceed::prelude::*;
335c68be7a2SJeremy L Thompson     /// # fn main() -> Result<(), libceed::CeedError> {
3369df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
3379df49d7eSJed Brown     /// let nelem = 3;
3389df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
3399df49d7eSJed Brown     /// for i in 0..nelem {
3409df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
3419df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
3429df49d7eSJed Brown     /// }
343c68be7a2SJeremy L Thompson     /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?;
3449df49d7eSJed Brown     ///
345c68be7a2SJeremy L Thompson     /// let x = ceed.vector_from_slice(&[0., 1., 2., 3.])?;
346c68be7a2SJeremy L Thompson     /// let mut y = ceed.vector(nelem * 2)?;
3479df49d7eSJed Brown     /// y.set_value(0.0);
3489df49d7eSJed Brown     ///
349c68be7a2SJeremy L Thompson     /// r.apply(TransposeMode::NoTranspose, &x, &mut y)?;
3509df49d7eSJed Brown     ///
3519df49d7eSJed Brown     /// y.view().iter().enumerate().for_each(|(i, arr)| {
3529df49d7eSJed Brown     ///     assert_eq!(
3539df49d7eSJed Brown     ///         *arr,
35480a9ef05SNatalie Beams     ///         ((i + 1) / 2) as Scalar,
3559df49d7eSJed Brown     ///         "Incorrect value in restricted vector"
3569df49d7eSJed Brown     ///     );
3579df49d7eSJed Brown     /// });
358c68be7a2SJeremy L Thompson     /// # Ok(())
359c68be7a2SJeremy L Thompson     /// # }
3609df49d7eSJed Brown     /// ```
3619df49d7eSJed Brown     pub fn apply(&self, tmode: TransposeMode, u: &Vector, ru: &mut Vector) -> crate::Result<i32> {
3629df49d7eSJed Brown         let tmode = tmode as bind_ceed::CeedTransposeMode;
3639df49d7eSJed Brown         let ierr = unsafe {
3649df49d7eSJed Brown             bind_ceed::CeedElemRestrictionApply(
3659df49d7eSJed Brown                 self.ptr,
3669df49d7eSJed Brown                 tmode,
3679df49d7eSJed Brown                 u.ptr,
3689df49d7eSJed Brown                 ru.ptr,
3699df49d7eSJed Brown                 bind_ceed::CEED_REQUEST_IMMEDIATE,
3709df49d7eSJed Brown             )
3719df49d7eSJed Brown         };
3729df49d7eSJed Brown         self.ceed.check_error(ierr)
3739df49d7eSJed Brown     }
3749df49d7eSJed Brown 
3759df49d7eSJed Brown     /// Returns the Lvector component stride
3769df49d7eSJed Brown     ///
3779df49d7eSJed Brown     /// ```
3789df49d7eSJed Brown     /// # use libceed::prelude::*;
379c68be7a2SJeremy L Thompson     /// # fn main() -> Result<(), libceed::CeedError> {
3809df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
3819df49d7eSJed Brown     /// let nelem = 3;
3829df49d7eSJed Brown     /// let compstride = 1;
3839df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
3849df49d7eSJed Brown     /// for i in 0..nelem {
3859df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
3869df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
3879df49d7eSJed Brown     /// }
388c68be7a2SJeremy L Thompson     /// let r = ceed.elem_restriction(nelem, 2, 1, compstride, nelem + 1, MemType::Host, &ind)?;
3899df49d7eSJed Brown     ///
3909df49d7eSJed Brown     /// let c = r.comp_stride();
3919df49d7eSJed Brown     /// assert_eq!(c, compstride, "Incorrect component stride");
392c68be7a2SJeremy L Thompson     /// # Ok(())
393c68be7a2SJeremy L Thompson     /// # }
3949df49d7eSJed Brown     /// ```
3959df49d7eSJed Brown     pub fn comp_stride(&self) -> usize {
3969df49d7eSJed Brown         let mut compstride = 0;
3979df49d7eSJed Brown         unsafe { bind_ceed::CeedElemRestrictionGetCompStride(self.ptr, &mut compstride) };
3989df49d7eSJed Brown         usize::try_from(compstride).unwrap()
3999df49d7eSJed Brown     }
4009df49d7eSJed Brown 
4019df49d7eSJed Brown     /// Returns the total number of elements in the range of a ElemRestriction
4029df49d7eSJed Brown     ///
4039df49d7eSJed Brown     /// ```
4049df49d7eSJed Brown     /// # use libceed::prelude::*;
405c68be7a2SJeremy L Thompson     /// # fn main() -> Result<(), libceed::CeedError> {
4069df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
4079df49d7eSJed Brown     /// let nelem = 3;
4089df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
4099df49d7eSJed Brown     /// for i in 0..nelem {
4109df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
4119df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
4129df49d7eSJed Brown     /// }
413c68be7a2SJeremy L Thompson     /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?;
4149df49d7eSJed Brown     ///
4159df49d7eSJed Brown     /// let n = r.num_elements();
4169df49d7eSJed Brown     /// assert_eq!(n, nelem, "Incorrect number of elements");
417c68be7a2SJeremy L Thompson     /// # Ok(())
418c68be7a2SJeremy L Thompson     /// # }
4199df49d7eSJed Brown     /// ```
4209df49d7eSJed Brown     pub fn num_elements(&self) -> usize {
4219df49d7eSJed Brown         let mut numelem = 0;
4229df49d7eSJed Brown         unsafe { bind_ceed::CeedElemRestrictionGetNumElements(self.ptr, &mut numelem) };
4239df49d7eSJed Brown         usize::try_from(numelem).unwrap()
4249df49d7eSJed Brown     }
4259df49d7eSJed Brown 
4269df49d7eSJed Brown     /// Returns the size of elements in the ElemRestriction
4279df49d7eSJed Brown     ///
4289df49d7eSJed Brown     /// ```
4299df49d7eSJed Brown     /// # use libceed::prelude::*;
430c68be7a2SJeremy L Thompson     /// # fn main() -> Result<(), libceed::CeedError> {
4319df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
4329df49d7eSJed Brown     /// let nelem = 3;
4339df49d7eSJed Brown     /// let elem_size = 2;
4349df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
4359df49d7eSJed Brown     /// for i in 0..nelem {
4369df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
4379df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
4389df49d7eSJed Brown     /// }
439c68be7a2SJeremy L Thompson     /// let r = ceed.elem_restriction(nelem, elem_size, 1, 1, nelem + 1, MemType::Host, &ind)?;
4409df49d7eSJed Brown     ///
4419df49d7eSJed Brown     /// let e = r.elem_size();
4429df49d7eSJed Brown     /// assert_eq!(e, elem_size, "Incorrect element size");
443c68be7a2SJeremy L Thompson     /// # Ok(())
444c68be7a2SJeremy L Thompson     /// # }
4459df49d7eSJed Brown     /// ```
4469df49d7eSJed Brown     pub fn elem_size(&self) -> usize {
4479df49d7eSJed Brown         let mut elemsize = 0;
4489df49d7eSJed Brown         unsafe { bind_ceed::CeedElemRestrictionGetElementSize(self.ptr, &mut elemsize) };
4499df49d7eSJed Brown         usize::try_from(elemsize).unwrap()
4509df49d7eSJed Brown     }
4519df49d7eSJed Brown 
4529df49d7eSJed Brown     /// Returns the size of the Lvector for an ElemRestriction
4539df49d7eSJed Brown     ///
4549df49d7eSJed Brown     /// ```
4559df49d7eSJed Brown     /// # use libceed::prelude::*;
456c68be7a2SJeremy L Thompson     /// # fn main() -> Result<(), libceed::CeedError> {
4579df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
4589df49d7eSJed Brown     /// let nelem = 3;
4599df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
4609df49d7eSJed Brown     /// for i in 0..nelem {
4619df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
4629df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
4639df49d7eSJed Brown     /// }
464c68be7a2SJeremy L Thompson     /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?;
4659df49d7eSJed Brown     ///
4669df49d7eSJed Brown     /// let lsize = r.lvector_size();
4679df49d7eSJed Brown     /// assert_eq!(lsize, nelem + 1);
468c68be7a2SJeremy L Thompson     /// # Ok(())
469c68be7a2SJeremy L Thompson     /// # }
4709df49d7eSJed Brown     /// ```
4719df49d7eSJed Brown     pub fn lvector_size(&self) -> usize {
4729df49d7eSJed Brown         let mut lsize = 0;
4739df49d7eSJed Brown         unsafe { bind_ceed::CeedElemRestrictionGetLVectorSize(self.ptr, &mut lsize) };
4749df49d7eSJed Brown         usize::try_from(lsize).unwrap()
4759df49d7eSJed Brown     }
4769df49d7eSJed Brown 
4779df49d7eSJed Brown     /// Returns the number of components in the elements of an ElemRestriction
4789df49d7eSJed Brown     ///
4799df49d7eSJed Brown     /// ```
4809df49d7eSJed Brown     /// # use libceed::prelude::*;
481c68be7a2SJeremy L Thompson     /// # fn main() -> Result<(), libceed::CeedError> {
4829df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
4839df49d7eSJed Brown     /// let nelem = 3;
4849df49d7eSJed Brown     /// let ncomp = 42;
4859df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
4869df49d7eSJed Brown     /// for i in 0..nelem {
4879df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
4889df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
4899df49d7eSJed Brown     /// }
490c68be7a2SJeremy L Thompson     /// let r = ceed.elem_restriction(nelem, 2, 42, 1, ncomp * (nelem + 1), MemType::Host, &ind)?;
4919df49d7eSJed Brown     ///
4929df49d7eSJed Brown     /// let n = r.num_components();
4939df49d7eSJed Brown     /// assert_eq!(n, ncomp, "Incorrect number of components");
494c68be7a2SJeremy L Thompson     /// # Ok(())
495c68be7a2SJeremy L Thompson     /// # }
4969df49d7eSJed Brown     /// ```
4979df49d7eSJed Brown     pub fn num_components(&self) -> usize {
4989df49d7eSJed Brown         let mut ncomp = 0;
4999df49d7eSJed Brown         unsafe { bind_ceed::CeedElemRestrictionGetNumComponents(self.ptr, &mut ncomp) };
5009df49d7eSJed Brown         usize::try_from(ncomp).unwrap()
5019df49d7eSJed Brown     }
5029df49d7eSJed Brown 
5039df49d7eSJed Brown     /// Returns the multiplicity of nodes in an ElemRestriction
5049df49d7eSJed Brown     ///
5059df49d7eSJed Brown     /// ```
5069df49d7eSJed Brown     /// # use libceed::prelude::*;
507c68be7a2SJeremy L Thompson     /// # fn main() -> Result<(), libceed::CeedError> {
5089df49d7eSJed Brown     /// # let ceed = libceed::Ceed::default_init();
5099df49d7eSJed Brown     /// let nelem = 3;
5109df49d7eSJed Brown     /// let mut ind: Vec<i32> = vec![0; 2 * nelem];
5119df49d7eSJed Brown     /// for i in 0..nelem {
5129df49d7eSJed Brown     ///     ind[2 * i + 0] = i as i32;
5139df49d7eSJed Brown     ///     ind[2 * i + 1] = (i + 1) as i32;
5149df49d7eSJed Brown     /// }
515c68be7a2SJeremy L Thompson     /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?;
5169df49d7eSJed Brown     ///
517c68be7a2SJeremy L Thompson     /// let mut mult = ceed.vector(nelem + 1)?;
5189df49d7eSJed Brown     /// mult.set_value(0.0);
5199df49d7eSJed Brown     ///
520c68be7a2SJeremy L Thompson     /// r.multiplicity(&mut mult)?;
5219df49d7eSJed Brown     ///
5229df49d7eSJed Brown     /// mult.view().iter().enumerate().for_each(|(i, arr)| {
5239df49d7eSJed Brown     ///     assert_eq!(
5249df49d7eSJed Brown     ///         if (i == 0 || i == nelem) { 1. } else { 2. },
5259df49d7eSJed Brown     ///         *arr,
5269df49d7eSJed Brown     ///         "Incorrect multiplicity array"
5279df49d7eSJed Brown     ///     );
5289df49d7eSJed Brown     /// });
529c68be7a2SJeremy L Thompson     /// # Ok(())
530c68be7a2SJeremy L Thompson     /// # }
5319df49d7eSJed Brown     /// ```
5329df49d7eSJed Brown     pub fn multiplicity(&self, mult: &mut Vector) -> crate::Result<i32> {
5339df49d7eSJed Brown         let ierr = unsafe { bind_ceed::CeedElemRestrictionGetMultiplicity(self.ptr, mult.ptr) };
5349df49d7eSJed Brown         self.ceed.check_error(ierr)
5359df49d7eSJed Brown     }
5369df49d7eSJed Brown }
5379df49d7eSJed Brown 
5389df49d7eSJed Brown // -----------------------------------------------------------------------------
539