xref: /libCEED/rust/libceed/src/elem_restriction.rs (revision d4cc18453651bd0f94c1a2e078b2646a92dafdcc)
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