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