1*9ba83ac0SJeremy L Thompson // Copyright (c) 2017-2026, Lawrence Livermore National Security, LLC and other CEED contributors. 23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 39df49d7eSJed Brown // 43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 59df49d7eSJed Brown // 63d8e8822SJeremy L Thompson // This file is part of CEED: http://github.com/ceed 79df49d7eSJed Brown 89df49d7eSJed Brown //! A Ceed ElemRestriction decomposes elements and groups the degrees of freedom 99df49d7eSJed Brown //! (dofs) according to the different elements they belong to. 109df49d7eSJed Brown 11eb07d68fSJeremy L Thompson use crate::{prelude::*, vector::Vector, TransposeMode}; 129df49d7eSJed Brown 139df49d7eSJed Brown // ----------------------------------------------------------------------------- 147ed177dbSJed Brown // ElemRestriction option 159df49d7eSJed Brown // ----------------------------------------------------------------------------- 16c68be7a2SJeremy L Thompson #[derive(Debug)] 179df49d7eSJed Brown pub enum ElemRestrictionOpt<'a> { 189df49d7eSJed Brown Some(&'a ElemRestriction<'a>), 199df49d7eSJed Brown None, 209df49d7eSJed Brown } 219df49d7eSJed Brown /// Construct a ElemRestrictionOpt reference from a ElemRestriction reference 229df49d7eSJed Brown impl<'a> From<&'a ElemRestriction<'_>> for ElemRestrictionOpt<'a> { from(rstr: &'a ElemRestriction) -> Self23edb2538eSJeremy L Thompson fn from(rstr: &'a ElemRestriction) -> Self { 24edb2538eSJeremy L Thompson debug_assert!(rstr.ptr != unsafe { bind_ceed::CEED_ELEMRESTRICTION_NONE }); 25edb2538eSJeremy L Thompson Self::Some(rstr) 269df49d7eSJed Brown } 279df49d7eSJed Brown } 289df49d7eSJed Brown impl<'a> ElemRestrictionOpt<'a> { 299df49d7eSJed Brown /// Transform a Rust libCEED ElemRestrictionOpt into C libCEED 309df49d7eSJed Brown /// CeedElemRestriction to_raw(&self) -> bind_ceed::CeedElemRestriction3178c2cefaSJeremy L Thompson pub(crate) fn to_raw(&self) -> bind_ceed::CeedElemRestriction { 329df49d7eSJed Brown match self { 33edb2538eSJeremy L Thompson Self::Some(rstr) => rstr.ptr, 349df49d7eSJed Brown Self::None => unsafe { bind_ceed::CEED_ELEMRESTRICTION_NONE }, 359df49d7eSJed Brown } 369df49d7eSJed Brown } 37e03682afSJeremy L Thompson 38e03682afSJeremy L Thompson /// Check if an ElemRestrictionOpt is Some 39e03682afSJeremy L Thompson /// 40e03682afSJeremy L Thompson /// ``` 41eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, ElemRestrictionOpt, MemType}; 424d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 43e03682afSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 44e03682afSJeremy L Thompson /// let nelem = 3; 45e03682afSJeremy L Thompson /// let mut ind: Vec<i32> = vec![0; 2 * nelem]; 46e03682afSJeremy L Thompson /// for i in 0..nelem { 47e03682afSJeremy L Thompson /// ind[2 * i + 0] = i as i32; 48e03682afSJeremy L Thompson /// ind[2 * i + 1] = (i + 1) as i32; 49e03682afSJeremy L Thompson /// } 50e03682afSJeremy L Thompson /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?; 51e03682afSJeremy L Thompson /// let r_opt = ElemRestrictionOpt::from(&r); 52e03682afSJeremy L Thompson /// assert!(r_opt.is_some(), "Incorrect ElemRestrictionOpt"); 53e03682afSJeremy L Thompson /// 54e03682afSJeremy L Thompson /// let r_opt = ElemRestrictionOpt::None; 55e03682afSJeremy L Thompson /// assert!(!r_opt.is_some(), "Incorrect ElemRestrictionOpt"); 56e03682afSJeremy L Thompson /// # Ok(()) 57e03682afSJeremy L Thompson /// # } 58e03682afSJeremy L Thompson /// ``` is_some(&self) -> bool59e03682afSJeremy L Thompson pub fn is_some(&self) -> bool { 60e03682afSJeremy L Thompson match self { 61e03682afSJeremy L Thompson Self::Some(_) => true, 62e03682afSJeremy L Thompson Self::None => false, 63e03682afSJeremy L Thompson } 64e03682afSJeremy L Thompson } 65e03682afSJeremy L Thompson 66e03682afSJeremy L Thompson /// Check if an ElemRestrictionOpt is None 67e03682afSJeremy L Thompson /// 68e03682afSJeremy L Thompson /// ``` 69eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, ElemRestrictionOpt, MemType}; 704d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 71e03682afSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 72e03682afSJeremy L Thompson /// let nelem = 3; 73e03682afSJeremy L Thompson /// let mut ind: Vec<i32> = vec![0; 2 * nelem]; 74e03682afSJeremy L Thompson /// for i in 0..nelem { 75e03682afSJeremy L Thompson /// ind[2 * i + 0] = i as i32; 76e03682afSJeremy L Thompson /// ind[2 * i + 1] = (i + 1) as i32; 77e03682afSJeremy L Thompson /// } 78e03682afSJeremy L Thompson /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?; 79e03682afSJeremy L Thompson /// let r_opt = ElemRestrictionOpt::from(&r); 80e03682afSJeremy L Thompson /// assert!(!r_opt.is_none(), "Incorrect ElemRestrictionOpt"); 81e03682afSJeremy L Thompson /// 82e03682afSJeremy L Thompson /// let r_opt = ElemRestrictionOpt::None; 83e03682afSJeremy L Thompson /// assert!(r_opt.is_none(), "Incorrect ElemRestrictionOpt"); 84e03682afSJeremy L Thompson /// # Ok(()) 85e03682afSJeremy L Thompson /// # } 86e03682afSJeremy L Thompson /// ``` is_none(&self) -> bool87e03682afSJeremy L Thompson pub fn is_none(&self) -> bool { 88e03682afSJeremy L Thompson match self { 89e03682afSJeremy L Thompson Self::Some(_) => false, 90e03682afSJeremy L Thompson Self::None => true, 91e03682afSJeremy L Thompson } 92e03682afSJeremy L Thompson } 939df49d7eSJed Brown } 949df49d7eSJed Brown 959df49d7eSJed Brown // ----------------------------------------------------------------------------- 967ed177dbSJed Brown // ElemRestriction context wrapper 979df49d7eSJed Brown // ----------------------------------------------------------------------------- 98c68be7a2SJeremy L Thompson #[derive(Debug)] 999df49d7eSJed Brown pub struct ElemRestriction<'a> { 1009df49d7eSJed Brown pub(crate) ptr: bind_ceed::CeedElemRestriction, 1011142270cSJeremy L Thompson _lifeline: PhantomData<&'a ()>, 1029df49d7eSJed Brown } 1039df49d7eSJed Brown 1049df49d7eSJed Brown // ----------------------------------------------------------------------------- 1059df49d7eSJed Brown // Destructor 1069df49d7eSJed Brown // ----------------------------------------------------------------------------- 1079df49d7eSJed Brown impl<'a> Drop for ElemRestriction<'a> { drop(&mut self)1089df49d7eSJed Brown fn drop(&mut self) { 1099df49d7eSJed Brown unsafe { 1109df49d7eSJed Brown if self.ptr != bind_ceed::CEED_ELEMRESTRICTION_NONE { 1119df49d7eSJed Brown bind_ceed::CeedElemRestrictionDestroy(&mut self.ptr); 1129df49d7eSJed Brown } 1139df49d7eSJed Brown } 1149df49d7eSJed Brown } 1159df49d7eSJed Brown } 1169df49d7eSJed Brown 1179df49d7eSJed Brown // ----------------------------------------------------------------------------- 1189df49d7eSJed Brown // Display 1199df49d7eSJed Brown // ----------------------------------------------------------------------------- 1209df49d7eSJed Brown impl<'a> fmt::Display for ElemRestriction<'a> { 1219df49d7eSJed Brown /// View an ElemRestriction 1229df49d7eSJed Brown /// 1239df49d7eSJed Brown /// ``` 124eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, MemType}; 1254d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 1269df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 1279df49d7eSJed Brown /// let nelem = 3; 1289df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * nelem]; 1299df49d7eSJed Brown /// for i in 0..nelem { 1309df49d7eSJed Brown /// ind[2 * i + 0] = i as i32; 1319df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32; 1329df49d7eSJed Brown /// } 133c68be7a2SJeremy L Thompson /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?; 1349df49d7eSJed Brown /// println!("{}", r); 135c68be7a2SJeremy L Thompson /// # Ok(()) 136c68be7a2SJeremy L Thompson /// # } 1379df49d7eSJed Brown /// ``` fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1389df49d7eSJed Brown fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1399df49d7eSJed Brown let mut ptr = std::ptr::null_mut(); 1409df49d7eSJed Brown let mut sizeloc = crate::MAX_BUFFER_LENGTH; 1419df49d7eSJed Brown let cstring = unsafe { 1429df49d7eSJed Brown let file = bind_ceed::open_memstream(&mut ptr, &mut sizeloc); 1439df49d7eSJed Brown bind_ceed::CeedElemRestrictionView(self.ptr, file); 1449df49d7eSJed Brown bind_ceed::fclose(file); 1459df49d7eSJed Brown CString::from_raw(ptr) 1469df49d7eSJed Brown }; 1479df49d7eSJed Brown cstring.to_string_lossy().fmt(f) 1489df49d7eSJed Brown } 1499df49d7eSJed Brown } 1509df49d7eSJed Brown 1519df49d7eSJed Brown // ----------------------------------------------------------------------------- 1529df49d7eSJed Brown // Implementations 1539df49d7eSJed Brown // ----------------------------------------------------------------------------- 1549df49d7eSJed Brown impl<'a> ElemRestriction<'a> { 1559df49d7eSJed Brown // Constructors 15678c2cefaSJeremy L Thompson #[allow(clippy::too_many_arguments)] create( ceed: &crate::Ceed, nelem: usize, elemsize: usize, ncomp: usize, compstride: usize, lsize: usize, mtype: crate::MemType, offsets: &[i32], ) -> crate::Result<Self>1579df49d7eSJed Brown pub fn create( 158594ef120SJeremy L Thompson ceed: &crate::Ceed, 1599df49d7eSJed Brown nelem: usize, 1609df49d7eSJed Brown elemsize: usize, 1619df49d7eSJed Brown ncomp: usize, 1629df49d7eSJed Brown compstride: usize, 1639df49d7eSJed Brown lsize: usize, 1649df49d7eSJed Brown mtype: crate::MemType, 1659df49d7eSJed Brown offsets: &[i32], 1669df49d7eSJed Brown ) -> crate::Result<Self> { 1679df49d7eSJed Brown let mut ptr = std::ptr::null_mut(); 1689df49d7eSJed Brown let (nelem, elemsize, ncomp, compstride, lsize, mtype) = ( 1699df49d7eSJed Brown i32::try_from(nelem).unwrap(), 1709df49d7eSJed Brown i32::try_from(elemsize).unwrap(), 1719df49d7eSJed Brown i32::try_from(ncomp).unwrap(), 1729df49d7eSJed Brown i32::try_from(compstride).unwrap(), 173e79b91d9SJeremy L Thompson isize::try_from(lsize).unwrap(), 1749df49d7eSJed Brown mtype as bind_ceed::CeedMemType, 1759df49d7eSJed Brown ); 176656ef1e5SJeremy L Thompson ceed.check_error(unsafe { 1779df49d7eSJed Brown bind_ceed::CeedElemRestrictionCreate( 1789df49d7eSJed Brown ceed.ptr, 1799df49d7eSJed Brown nelem, 1809df49d7eSJed Brown elemsize, 1819df49d7eSJed Brown ncomp, 1829df49d7eSJed Brown compstride, 1839df49d7eSJed Brown lsize, 1849df49d7eSJed Brown mtype, 1859df49d7eSJed Brown crate::CopyMode::CopyValues as bind_ceed::CeedCopyMode, 1869df49d7eSJed Brown offsets.as_ptr(), 1879df49d7eSJed Brown &mut ptr, 1889df49d7eSJed Brown ) 189656ef1e5SJeremy L Thompson })?; 1901142270cSJeremy L Thompson Ok(Self { 1911142270cSJeremy L Thompson ptr, 1921142270cSJeremy L Thompson _lifeline: PhantomData, 1931142270cSJeremy L Thompson }) 1949df49d7eSJed Brown } 1959df49d7eSJed Brown from_raw(ptr: bind_ceed::CeedElemRestriction) -> crate::Result<Self>1962b671a0aSJeremy L Thompson pub(crate) unsafe fn from_raw(ptr: bind_ceed::CeedElemRestriction) -> crate::Result<Self> { 197e03fef56SJeremy L Thompson Ok(Self { 198e03fef56SJeremy L Thompson ptr, 199e03fef56SJeremy L Thompson _lifeline: PhantomData, 200e03fef56SJeremy L Thompson }) 201e03fef56SJeremy L Thompson } 202e03fef56SJeremy L Thompson 20378c2cefaSJeremy L Thompson #[allow(clippy::too_many_arguments)] create_oriented( ceed: &crate::Ceed, nelem: usize, elemsize: usize, ncomp: usize, compstride: usize, lsize: usize, mtype: crate::MemType, offsets: &[i32], orients: &[bool], ) -> crate::Result<Self>204709403c1SSebastian Grimberg pub fn create_oriented( 205709403c1SSebastian Grimberg ceed: &crate::Ceed, 206709403c1SSebastian Grimberg nelem: usize, 207709403c1SSebastian Grimberg elemsize: usize, 208709403c1SSebastian Grimberg ncomp: usize, 209709403c1SSebastian Grimberg compstride: usize, 210709403c1SSebastian Grimberg lsize: usize, 211709403c1SSebastian Grimberg mtype: crate::MemType, 212709403c1SSebastian Grimberg offsets: &[i32], 213709403c1SSebastian Grimberg orients: &[bool], 214709403c1SSebastian Grimberg ) -> crate::Result<Self> { 215709403c1SSebastian Grimberg let mut ptr = std::ptr::null_mut(); 216709403c1SSebastian Grimberg let (nelem, elemsize, ncomp, compstride, lsize, mtype) = ( 217709403c1SSebastian Grimberg i32::try_from(nelem).unwrap(), 218709403c1SSebastian Grimberg i32::try_from(elemsize).unwrap(), 219709403c1SSebastian Grimberg i32::try_from(ncomp).unwrap(), 220709403c1SSebastian Grimberg i32::try_from(compstride).unwrap(), 221709403c1SSebastian Grimberg isize::try_from(lsize).unwrap(), 222709403c1SSebastian Grimberg mtype as bind_ceed::CeedMemType, 223709403c1SSebastian Grimberg ); 224656ef1e5SJeremy L Thompson ceed.check_error(unsafe { 225709403c1SSebastian Grimberg bind_ceed::CeedElemRestrictionCreateOriented( 226709403c1SSebastian Grimberg ceed.ptr, 227709403c1SSebastian Grimberg nelem, 228709403c1SSebastian Grimberg elemsize, 229709403c1SSebastian Grimberg ncomp, 230709403c1SSebastian Grimberg compstride, 231709403c1SSebastian Grimberg lsize, 232709403c1SSebastian Grimberg mtype, 233709403c1SSebastian Grimberg crate::CopyMode::CopyValues as bind_ceed::CeedCopyMode, 234709403c1SSebastian Grimberg offsets.as_ptr(), 235709403c1SSebastian Grimberg orients.as_ptr(), 236709403c1SSebastian Grimberg &mut ptr, 237709403c1SSebastian Grimberg ) 238656ef1e5SJeremy L Thompson })?; 239709403c1SSebastian Grimberg Ok(Self { 240709403c1SSebastian Grimberg ptr, 241709403c1SSebastian Grimberg _lifeline: PhantomData, 242709403c1SSebastian Grimberg }) 243709403c1SSebastian Grimberg } 244709403c1SSebastian Grimberg 24578c2cefaSJeremy L Thompson #[allow(clippy::too_many_arguments)] create_curl_oriented( ceed: &crate::Ceed, nelem: usize, elemsize: usize, ncomp: usize, compstride: usize, lsize: usize, mtype: crate::MemType, offsets: &[i32], curlorients: &[i8], ) -> crate::Result<Self>246709403c1SSebastian Grimberg pub fn create_curl_oriented( 247709403c1SSebastian Grimberg ceed: &crate::Ceed, 248709403c1SSebastian Grimberg nelem: usize, 249709403c1SSebastian Grimberg elemsize: usize, 250709403c1SSebastian Grimberg ncomp: usize, 251709403c1SSebastian Grimberg compstride: usize, 252709403c1SSebastian Grimberg lsize: usize, 253709403c1SSebastian Grimberg mtype: crate::MemType, 254709403c1SSebastian Grimberg offsets: &[i32], 255709403c1SSebastian Grimberg curlorients: &[i8], 256709403c1SSebastian Grimberg ) -> crate::Result<Self> { 257709403c1SSebastian Grimberg let mut ptr = std::ptr::null_mut(); 258709403c1SSebastian Grimberg let (nelem, elemsize, ncomp, compstride, lsize, mtype) = ( 259709403c1SSebastian Grimberg i32::try_from(nelem).unwrap(), 260709403c1SSebastian Grimberg i32::try_from(elemsize).unwrap(), 261709403c1SSebastian Grimberg i32::try_from(ncomp).unwrap(), 262709403c1SSebastian Grimberg i32::try_from(compstride).unwrap(), 263709403c1SSebastian Grimberg isize::try_from(lsize).unwrap(), 264709403c1SSebastian Grimberg mtype as bind_ceed::CeedMemType, 265709403c1SSebastian Grimberg ); 266656ef1e5SJeremy L Thompson ceed.check_error(unsafe { 267709403c1SSebastian Grimberg bind_ceed::CeedElemRestrictionCreateCurlOriented( 268709403c1SSebastian Grimberg ceed.ptr, 269709403c1SSebastian Grimberg nelem, 270709403c1SSebastian Grimberg elemsize, 271709403c1SSebastian Grimberg ncomp, 272709403c1SSebastian Grimberg compstride, 273709403c1SSebastian Grimberg lsize, 274709403c1SSebastian Grimberg mtype, 275709403c1SSebastian Grimberg crate::CopyMode::CopyValues as bind_ceed::CeedCopyMode, 276709403c1SSebastian Grimberg offsets.as_ptr(), 277709403c1SSebastian Grimberg curlorients.as_ptr(), 278709403c1SSebastian Grimberg &mut ptr, 279709403c1SSebastian Grimberg ) 280656ef1e5SJeremy L Thompson })?; 281709403c1SSebastian Grimberg Ok(Self { 282709403c1SSebastian Grimberg ptr, 283709403c1SSebastian Grimberg _lifeline: PhantomData, 284709403c1SSebastian Grimberg }) 285709403c1SSebastian Grimberg } 286709403c1SSebastian Grimberg create_strided( ceed: &crate::Ceed, nelem: usize, elemsize: usize, ncomp: usize, lsize: usize, strides: [i32; 3], ) -> crate::Result<Self>2879df49d7eSJed Brown pub fn create_strided( 288594ef120SJeremy L Thompson ceed: &crate::Ceed, 2899df49d7eSJed Brown nelem: usize, 2909df49d7eSJed Brown elemsize: usize, 2919df49d7eSJed Brown ncomp: usize, 2929df49d7eSJed Brown lsize: usize, 2939df49d7eSJed Brown strides: [i32; 3], 2949df49d7eSJed Brown ) -> crate::Result<Self> { 2959df49d7eSJed Brown let mut ptr = std::ptr::null_mut(); 2969df49d7eSJed Brown let (nelem, elemsize, ncomp, lsize) = ( 2979df49d7eSJed Brown i32::try_from(nelem).unwrap(), 2989df49d7eSJed Brown i32::try_from(elemsize).unwrap(), 2999df49d7eSJed Brown i32::try_from(ncomp).unwrap(), 300e79b91d9SJeremy L Thompson isize::try_from(lsize).unwrap(), 3019df49d7eSJed Brown ); 302656ef1e5SJeremy L Thompson ceed.check_error(unsafe { 3039df49d7eSJed Brown bind_ceed::CeedElemRestrictionCreateStrided( 3049df49d7eSJed Brown ceed.ptr, 3059df49d7eSJed Brown nelem, 3069df49d7eSJed Brown elemsize, 3079df49d7eSJed Brown ncomp, 3089df49d7eSJed Brown lsize, 3099df49d7eSJed Brown strides.as_ptr(), 3109df49d7eSJed Brown &mut ptr, 3119df49d7eSJed Brown ) 312656ef1e5SJeremy L Thompson })?; 3131142270cSJeremy L Thompson Ok(Self { 3141142270cSJeremy L Thompson ptr, 3151142270cSJeremy L Thompson _lifeline: PhantomData, 3161142270cSJeremy L Thompson }) 3171142270cSJeremy L Thompson } 3181142270cSJeremy L Thompson 31911544396SJeremy L Thompson // Raw Ceed for error handling 32011544396SJeremy L Thompson #[doc(hidden)] ceed(&self) -> bind_ceed::Ceed32111544396SJeremy L Thompson fn ceed(&self) -> bind_ceed::Ceed { 32211544396SJeremy L Thompson unsafe { bind_ceed::CeedElemRestrictionReturnCeed(self.ptr) } 32311544396SJeremy L Thompson } 32411544396SJeremy L Thompson 3251142270cSJeremy L Thompson // Error handling 3261142270cSJeremy L Thompson #[doc(hidden)] check_error(&self, ierr: i32) -> crate::Result<i32>3271142270cSJeremy L Thompson fn check_error(&self, ierr: i32) -> crate::Result<i32> { 32811544396SJeremy L Thompson crate::check_error(|| self.ceed(), ierr) 3299df49d7eSJed Brown } 3309df49d7eSJed Brown 3319df49d7eSJed Brown /// Create an Lvector for an ElemRestriction 3329df49d7eSJed Brown /// 3339df49d7eSJed Brown /// ``` 334eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, MemType}; 3354d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 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 lvector = r.create_lvector()?; 3469df49d7eSJed Brown /// 3479df49d7eSJed Brown /// assert_eq!(lvector.length(), nelem + 1, "Incorrect Lvector size"); 348c68be7a2SJeremy L Thompson /// # Ok(()) 349c68be7a2SJeremy L Thompson /// # } 3509df49d7eSJed Brown /// ``` create_lvector<'b>(&self) -> crate::Result<Vector<'b>>351594ef120SJeremy L Thompson pub fn create_lvector<'b>(&self) -> crate::Result<Vector<'b>> { 3529df49d7eSJed Brown let mut ptr_lvector = std::ptr::null_mut(); 3539df49d7eSJed Brown let null = std::ptr::null_mut() as *mut _; 354656ef1e5SJeremy L Thompson self.check_error(unsafe { 355656ef1e5SJeremy L Thompson bind_ceed::CeedElemRestrictionCreateVector(self.ptr, &mut ptr_lvector, null) 356656ef1e5SJeremy L Thompson })?; 3572b671a0aSJeremy L Thompson unsafe { Vector::from_raw(ptr_lvector) } 3589df49d7eSJed Brown } 3599df49d7eSJed Brown 3609df49d7eSJed Brown /// Create an Evector for an ElemRestriction 3619df49d7eSJed Brown /// 3629df49d7eSJed Brown /// ``` 363eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, MemType}; 3644d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 3659df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 3669df49d7eSJed Brown /// let nelem = 3; 3679df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * nelem]; 3689df49d7eSJed Brown /// for i in 0..nelem { 3699df49d7eSJed Brown /// ind[2 * i + 0] = i as i32; 3709df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32; 3719df49d7eSJed Brown /// } 372c68be7a2SJeremy L Thompson /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?; 3739df49d7eSJed Brown /// 374c68be7a2SJeremy L Thompson /// let evector = r.create_evector()?; 3759df49d7eSJed Brown /// 3769df49d7eSJed Brown /// assert_eq!(evector.length(), nelem * 2, "Incorrect Evector size"); 377c68be7a2SJeremy L Thompson /// # Ok(()) 378c68be7a2SJeremy L Thompson /// # } 3799df49d7eSJed Brown /// ``` create_evector<'b>(&self) -> crate::Result<Vector<'b>>380594ef120SJeremy L Thompson pub fn create_evector<'b>(&self) -> crate::Result<Vector<'b>> { 3819df49d7eSJed Brown let mut ptr_evector = std::ptr::null_mut(); 3829df49d7eSJed Brown let null = std::ptr::null_mut() as *mut _; 383656ef1e5SJeremy L Thompson self.check_error(unsafe { 384656ef1e5SJeremy L Thompson bind_ceed::CeedElemRestrictionCreateVector(self.ptr, null, &mut ptr_evector) 385656ef1e5SJeremy L Thompson })?; 3862b671a0aSJeremy L Thompson unsafe { Vector::from_raw(ptr_evector) } 3879df49d7eSJed Brown } 3889df49d7eSJed Brown 3899df49d7eSJed Brown /// Create Vectors for an ElemRestriction 3909df49d7eSJed Brown /// 3919df49d7eSJed Brown /// ``` 392eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, MemType}; 3934d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 3949df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 3959df49d7eSJed Brown /// let nelem = 3; 3969df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * nelem]; 3979df49d7eSJed Brown /// for i in 0..nelem { 3989df49d7eSJed Brown /// ind[2 * i + 0] = i as i32; 3999df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32; 4009df49d7eSJed Brown /// } 401c68be7a2SJeremy L Thompson /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?; 4029df49d7eSJed Brown /// 403c68be7a2SJeremy L Thompson /// let (lvector, evector) = r.create_vectors()?; 4049df49d7eSJed Brown /// 4059df49d7eSJed Brown /// assert_eq!(lvector.length(), nelem + 1, "Incorrect Lvector size"); 4069df49d7eSJed Brown /// assert_eq!(evector.length(), nelem * 2, "Incorrect Evector size"); 407c68be7a2SJeremy L Thompson /// # Ok(()) 408c68be7a2SJeremy L Thompson /// # } 4099df49d7eSJed Brown /// ``` create_vectors<'b, 'c>(&self) -> crate::Result<(Vector<'b>, Vector<'c>)>410594ef120SJeremy L Thompson pub fn create_vectors<'b, 'c>(&self) -> crate::Result<(Vector<'b>, Vector<'c>)> { 4119df49d7eSJed Brown let mut ptr_lvector = std::ptr::null_mut(); 4129df49d7eSJed Brown let mut ptr_evector = std::ptr::null_mut(); 413656ef1e5SJeremy L Thompson self.check_error(unsafe { 4149df49d7eSJed Brown bind_ceed::CeedElemRestrictionCreateVector(self.ptr, &mut ptr_lvector, &mut ptr_evector) 415656ef1e5SJeremy L Thompson })?; 4162b671a0aSJeremy L Thompson let lvector = unsafe { Vector::from_raw(ptr_lvector)? }; 4172b671a0aSJeremy L Thompson let evector = unsafe { Vector::from_raw(ptr_evector)? }; 4189df49d7eSJed Brown Ok((lvector, evector)) 4199df49d7eSJed Brown } 4209df49d7eSJed Brown 4219df49d7eSJed Brown /// Restrict an Lvector to an Evector or apply its transpose 4229df49d7eSJed Brown /// 4239df49d7eSJed Brown /// # arguments 4249df49d7eSJed Brown /// 4259df49d7eSJed Brown /// * `tmode` - Apply restriction or transpose 4269df49d7eSJed Brown /// * `u` - Input vector (of size `lsize` when `TransposeMode::NoTranspose`) 4279df49d7eSJed Brown /// * `ru` - Output vector (of shape `[nelem * elemsize]` when 4289df49d7eSJed Brown /// `TransposeMode::NoTranspose`). Ordering of the Evector is 4299df49d7eSJed Brown /// decided by the backend. 4309df49d7eSJed Brown /// 4319df49d7eSJed Brown /// ``` 432eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, MemType, Scalar, TransposeMode}; 4334d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 4349df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 4359df49d7eSJed Brown /// let nelem = 3; 4369df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * nelem]; 4379df49d7eSJed Brown /// for i in 0..nelem { 4389df49d7eSJed Brown /// ind[2 * i + 0] = i as i32; 4399df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32; 4409df49d7eSJed Brown /// } 441c68be7a2SJeremy L Thompson /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?; 4429df49d7eSJed Brown /// 443c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&[0., 1., 2., 3.])?; 444c68be7a2SJeremy L Thompson /// let mut y = ceed.vector(nelem * 2)?; 4459df49d7eSJed Brown /// y.set_value(0.0); 4469df49d7eSJed Brown /// 447c68be7a2SJeremy L Thompson /// r.apply(TransposeMode::NoTranspose, &x, &mut y)?; 4489df49d7eSJed Brown /// 449d3677ae8SJeremy L Thompson /// for (i, y) in y.view()?.iter().enumerate() { 4509df49d7eSJed Brown /// assert_eq!( 451d3677ae8SJeremy L Thompson /// *y, 45280a9ef05SNatalie Beams /// ((i + 1) / 2) as Scalar, 4539df49d7eSJed Brown /// "Incorrect value in restricted vector" 4549df49d7eSJed Brown /// ); 455d3677ae8SJeremy L Thompson /// } 456c68be7a2SJeremy L Thompson /// # Ok(()) 457c68be7a2SJeremy L Thompson /// # } 4589df49d7eSJed Brown /// ``` apply(&self, tmode: TransposeMode, u: &Vector, ru: &mut Vector) -> crate::Result<i32>4599df49d7eSJed Brown pub fn apply(&self, tmode: TransposeMode, u: &Vector, ru: &mut Vector) -> crate::Result<i32> { 4609df49d7eSJed Brown let tmode = tmode as bind_ceed::CeedTransposeMode; 461656ef1e5SJeremy L Thompson self.check_error(unsafe { 4629df49d7eSJed Brown bind_ceed::CeedElemRestrictionApply( 4639df49d7eSJed Brown self.ptr, 4649df49d7eSJed Brown tmode, 4659df49d7eSJed Brown u.ptr, 4669df49d7eSJed Brown ru.ptr, 4679df49d7eSJed Brown bind_ceed::CEED_REQUEST_IMMEDIATE, 4689df49d7eSJed Brown ) 469656ef1e5SJeremy L Thompson }) 4709df49d7eSJed Brown } 4719df49d7eSJed Brown 4729df49d7eSJed Brown /// Returns the Lvector component stride 4739df49d7eSJed Brown /// 4749df49d7eSJed Brown /// ``` 475eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, MemType}; 4764d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 4779df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 4789df49d7eSJed Brown /// let nelem = 3; 4799df49d7eSJed Brown /// let compstride = 1; 4809df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * nelem]; 4819df49d7eSJed Brown /// for i in 0..nelem { 4829df49d7eSJed Brown /// ind[2 * i + 0] = i as i32; 4839df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32; 4849df49d7eSJed Brown /// } 485c68be7a2SJeremy L Thompson /// let r = ceed.elem_restriction(nelem, 2, 1, compstride, nelem + 1, MemType::Host, &ind)?; 4869df49d7eSJed Brown /// 4879df49d7eSJed Brown /// let c = r.comp_stride(); 4889df49d7eSJed Brown /// assert_eq!(c, compstride, "Incorrect component stride"); 489c68be7a2SJeremy L Thompson /// # Ok(()) 490c68be7a2SJeremy L Thompson /// # } 4919df49d7eSJed Brown /// ``` comp_stride(&self) -> usize4929df49d7eSJed Brown pub fn comp_stride(&self) -> usize { 4939df49d7eSJed Brown let mut compstride = 0; 4949df49d7eSJed Brown unsafe { bind_ceed::CeedElemRestrictionGetCompStride(self.ptr, &mut compstride) }; 4959df49d7eSJed Brown usize::try_from(compstride).unwrap() 4969df49d7eSJed Brown } 4979df49d7eSJed Brown 4989df49d7eSJed Brown /// Returns the total number of elements in the range of a ElemRestriction 4999df49d7eSJed Brown /// 5009df49d7eSJed Brown /// ``` 501eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, MemType}; 5024d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 5039df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 5049df49d7eSJed Brown /// let nelem = 3; 5059df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * nelem]; 5069df49d7eSJed Brown /// for i in 0..nelem { 5079df49d7eSJed Brown /// ind[2 * i + 0] = i as i32; 5089df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32; 5099df49d7eSJed Brown /// } 510c68be7a2SJeremy L Thompson /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?; 5119df49d7eSJed Brown /// 5129df49d7eSJed Brown /// let n = r.num_elements(); 5139df49d7eSJed Brown /// assert_eq!(n, nelem, "Incorrect number of elements"); 514c68be7a2SJeremy L Thompson /// # Ok(()) 515c68be7a2SJeremy L Thompson /// # } 5169df49d7eSJed Brown /// ``` num_elements(&self) -> usize5179df49d7eSJed Brown pub fn num_elements(&self) -> usize { 5189df49d7eSJed Brown let mut numelem = 0; 5199df49d7eSJed Brown unsafe { bind_ceed::CeedElemRestrictionGetNumElements(self.ptr, &mut numelem) }; 5209df49d7eSJed Brown usize::try_from(numelem).unwrap() 5219df49d7eSJed Brown } 5229df49d7eSJed Brown 5239df49d7eSJed Brown /// Returns the size of elements in the ElemRestriction 5249df49d7eSJed Brown /// 5259df49d7eSJed Brown /// ``` 526eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, MemType}; 5274d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 5289df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 5299df49d7eSJed Brown /// let nelem = 3; 5309df49d7eSJed Brown /// let elem_size = 2; 5319df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * nelem]; 5329df49d7eSJed Brown /// for i in 0..nelem { 5339df49d7eSJed Brown /// ind[2 * i + 0] = i as i32; 5349df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32; 5359df49d7eSJed Brown /// } 536c68be7a2SJeremy L Thompson /// let r = ceed.elem_restriction(nelem, elem_size, 1, 1, nelem + 1, MemType::Host, &ind)?; 5379df49d7eSJed Brown /// 5389df49d7eSJed Brown /// let e = r.elem_size(); 5399df49d7eSJed Brown /// assert_eq!(e, elem_size, "Incorrect element size"); 540c68be7a2SJeremy L Thompson /// # Ok(()) 541c68be7a2SJeremy L Thompson /// # } 5429df49d7eSJed Brown /// ``` elem_size(&self) -> usize5439df49d7eSJed Brown pub fn elem_size(&self) -> usize { 5449df49d7eSJed Brown let mut elemsize = 0; 5459df49d7eSJed Brown unsafe { bind_ceed::CeedElemRestrictionGetElementSize(self.ptr, &mut elemsize) }; 5469df49d7eSJed Brown usize::try_from(elemsize).unwrap() 5479df49d7eSJed Brown } 5489df49d7eSJed Brown 5499df49d7eSJed Brown /// Returns the size of the Lvector for an ElemRestriction 5509df49d7eSJed Brown /// 5519df49d7eSJed Brown /// ``` 552eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, MemType}; 5534d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 5549df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 5559df49d7eSJed Brown /// let nelem = 3; 5569df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * nelem]; 5579df49d7eSJed Brown /// for i in 0..nelem { 5589df49d7eSJed Brown /// ind[2 * i + 0] = i as i32; 5599df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32; 5609df49d7eSJed Brown /// } 561c68be7a2SJeremy L Thompson /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?; 5629df49d7eSJed Brown /// 5639df49d7eSJed Brown /// let lsize = r.lvector_size(); 5649df49d7eSJed Brown /// assert_eq!(lsize, nelem + 1); 565c68be7a2SJeremy L Thompson /// # Ok(()) 566c68be7a2SJeremy L Thompson /// # } 5679df49d7eSJed Brown /// ``` lvector_size(&self) -> usize5689df49d7eSJed Brown pub fn lvector_size(&self) -> usize { 5699df49d7eSJed Brown let mut lsize = 0; 5709df49d7eSJed Brown unsafe { bind_ceed::CeedElemRestrictionGetLVectorSize(self.ptr, &mut lsize) }; 5719df49d7eSJed Brown usize::try_from(lsize).unwrap() 5729df49d7eSJed Brown } 5739df49d7eSJed Brown 5749df49d7eSJed Brown /// Returns the number of components in the elements of an ElemRestriction 5759df49d7eSJed Brown /// 5769df49d7eSJed Brown /// ``` 577eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, MemType}; 5784d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 5799df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 5809df49d7eSJed Brown /// let nelem = 3; 5819df49d7eSJed Brown /// let ncomp = 42; 5829df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * nelem]; 5839df49d7eSJed Brown /// for i in 0..nelem { 5849df49d7eSJed Brown /// ind[2 * i + 0] = i as i32; 5859df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32; 5869df49d7eSJed Brown /// } 587c68be7a2SJeremy L Thompson /// let r = ceed.elem_restriction(nelem, 2, 42, 1, ncomp * (nelem + 1), MemType::Host, &ind)?; 5889df49d7eSJed Brown /// 5899df49d7eSJed Brown /// let n = r.num_components(); 5909df49d7eSJed Brown /// assert_eq!(n, ncomp, "Incorrect number of components"); 591c68be7a2SJeremy L Thompson /// # Ok(()) 592c68be7a2SJeremy L Thompson /// # } 5939df49d7eSJed Brown /// ``` num_components(&self) -> usize5949df49d7eSJed Brown pub fn num_components(&self) -> usize { 5959df49d7eSJed Brown let mut ncomp = 0; 5969df49d7eSJed Brown unsafe { bind_ceed::CeedElemRestrictionGetNumComponents(self.ptr, &mut ncomp) }; 5979df49d7eSJed Brown usize::try_from(ncomp).unwrap() 5989df49d7eSJed Brown } 5999df49d7eSJed Brown 6009df49d7eSJed Brown /// Returns the multiplicity of nodes in an ElemRestriction 6019df49d7eSJed Brown /// 6029df49d7eSJed Brown /// ``` 603eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, MemType}; 6044d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 6059df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 6069df49d7eSJed Brown /// let nelem = 3; 6079df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * nelem]; 6089df49d7eSJed Brown /// for i in 0..nelem { 6099df49d7eSJed Brown /// ind[2 * i + 0] = i as i32; 6109df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32; 6119df49d7eSJed Brown /// } 612c68be7a2SJeremy L Thompson /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?; 6139df49d7eSJed Brown /// 614c68be7a2SJeremy L Thompson /// let mut mult = ceed.vector(nelem + 1)?; 6159df49d7eSJed Brown /// mult.set_value(0.0); 6169df49d7eSJed Brown /// 617c68be7a2SJeremy L Thompson /// r.multiplicity(&mut mult)?; 6189df49d7eSJed Brown /// 619d3677ae8SJeremy L Thompson /// for (i, m) in mult.view()?.iter().enumerate() { 6209df49d7eSJed Brown /// assert_eq!( 621d3677ae8SJeremy L Thompson /// *m, 6229df49d7eSJed Brown /// if (i == 0 || i == nelem) { 1. } else { 2. }, 623d3677ae8SJeremy L Thompson /// "Incorrect multiplicity value" 6249df49d7eSJed Brown /// ); 625d3677ae8SJeremy L Thompson /// } 626c68be7a2SJeremy L Thompson /// # Ok(()) 627c68be7a2SJeremy L Thompson /// # } 6289df49d7eSJed Brown /// ``` multiplicity(&self, mult: &mut Vector) -> crate::Result<i32>6299df49d7eSJed Brown pub fn multiplicity(&self, mult: &mut Vector) -> crate::Result<i32> { 630656ef1e5SJeremy L Thompson self.check_error(unsafe { 631656ef1e5SJeremy L Thompson bind_ceed::CeedElemRestrictionGetMultiplicity(self.ptr, mult.ptr) 632656ef1e5SJeremy L Thompson }) 6339df49d7eSJed Brown } 6349df49d7eSJed Brown } 6359df49d7eSJed Brown 6369df49d7eSJed Brown // ----------------------------------------------------------------------------- 637