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 Vector constitutes the main data structure and serves as input/output 189df49d7eSJed Brown //! for Ceed Operators. 199df49d7eSJed Brown 209df49d7eSJed Brown use std::{ 219df49d7eSJed Brown ops::{Deref, DerefMut}, 229df49d7eSJed Brown os::raw::c_char, 239df49d7eSJed Brown }; 249df49d7eSJed Brown 259df49d7eSJed Brown use crate::prelude::*; 269df49d7eSJed Brown 279df49d7eSJed Brown // ----------------------------------------------------------------------------- 289df49d7eSJed Brown // CeedVector option 299df49d7eSJed Brown // ----------------------------------------------------------------------------- 30*c68be7a2SJeremy L Thompson #[derive(Debug)] 319df49d7eSJed Brown pub enum VectorOpt<'a> { 329df49d7eSJed Brown Some(&'a Vector<'a>), 339df49d7eSJed Brown Active, 349df49d7eSJed Brown None, 359df49d7eSJed Brown } 369df49d7eSJed Brown /// Construct a VectorOpt reference from a Vector reference 379df49d7eSJed Brown impl<'a> From<&'a Vector<'_>> for VectorOpt<'a> { 389df49d7eSJed Brown fn from(vec: &'a Vector) -> Self { 399df49d7eSJed Brown debug_assert!(vec.ptr != unsafe { bind_ceed::CEED_VECTOR_ACTIVE }); 40*c68be7a2SJeremy L Thompson debug_assert!(vec.ptr != unsafe { bind_ceed::CEED_VECTOR_NONE }); 419df49d7eSJed Brown Self::Some(vec) 429df49d7eSJed Brown } 439df49d7eSJed Brown } 449df49d7eSJed Brown impl<'a> VectorOpt<'a> { 459df49d7eSJed Brown /// Transform a Rust libCEED VectorOpt into C libCEED CeedVector 469df49d7eSJed Brown pub(crate) fn to_raw(self) -> bind_ceed::CeedVector { 479df49d7eSJed Brown match self { 489df49d7eSJed Brown Self::Some(vec) => vec.ptr, 499df49d7eSJed Brown Self::Active => unsafe { bind_ceed::CEED_VECTOR_ACTIVE }, 50*c68be7a2SJeremy L Thompson Self::None => unsafe { bind_ceed::CEED_VECTOR_NONE }, 519df49d7eSJed Brown } 529df49d7eSJed Brown } 539df49d7eSJed Brown } 549df49d7eSJed Brown 559df49d7eSJed Brown // ----------------------------------------------------------------------------- 569df49d7eSJed Brown // CeedVector context wrapper 579df49d7eSJed Brown // ----------------------------------------------------------------------------- 589df49d7eSJed Brown #[derive(Debug)] 599df49d7eSJed Brown pub struct Vector<'a> { 609df49d7eSJed Brown ceed: &'a crate::Ceed, 619df49d7eSJed Brown pub(crate) ptr: bind_ceed::CeedVector, 629df49d7eSJed Brown } 639df49d7eSJed Brown impl From<&'_ Vector<'_>> for bind_ceed::CeedVector { 649df49d7eSJed Brown fn from(vec: &Vector) -> Self { 659df49d7eSJed Brown vec.ptr 669df49d7eSJed Brown } 679df49d7eSJed Brown } 689df49d7eSJed Brown 699df49d7eSJed Brown // ----------------------------------------------------------------------------- 709df49d7eSJed Brown // Destructor 719df49d7eSJed Brown // ----------------------------------------------------------------------------- 729df49d7eSJed Brown impl<'a> Drop for Vector<'a> { 739df49d7eSJed Brown fn drop(&mut self) { 749df49d7eSJed Brown let not_none_and_active = self.ptr != unsafe { bind_ceed::CEED_VECTOR_NONE } 759df49d7eSJed Brown && self.ptr != unsafe { bind_ceed::CEED_VECTOR_ACTIVE }; 769df49d7eSJed Brown 779df49d7eSJed Brown if not_none_and_active { 789df49d7eSJed Brown unsafe { bind_ceed::CeedVectorDestroy(&mut self.ptr) }; 799df49d7eSJed Brown } 809df49d7eSJed Brown } 819df49d7eSJed Brown } 829df49d7eSJed Brown 839df49d7eSJed Brown // ----------------------------------------------------------------------------- 849df49d7eSJed Brown // Display 859df49d7eSJed Brown // ----------------------------------------------------------------------------- 869df49d7eSJed Brown impl<'a> fmt::Display for Vector<'a> { 879df49d7eSJed Brown /// View a Vector 889df49d7eSJed Brown /// 899df49d7eSJed Brown /// ``` 909df49d7eSJed Brown /// # use libceed::prelude::*; 91*c68be7a2SJeremy L Thompson /// # fn main() -> Result<(), libceed::CeedError> { 929df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 93*c68be7a2SJeremy L Thompson /// let vec = libceed::vector::Vector::from_slice(&ceed, &[1., 2., 3.])?; 949df49d7eSJed Brown /// assert_eq!( 959df49d7eSJed Brown /// vec.to_string(), 969df49d7eSJed Brown /// "CeedVector length 3 979df49d7eSJed Brown /// 1.00000000 989df49d7eSJed Brown /// 2.00000000 999df49d7eSJed Brown /// 3.00000000 1009df49d7eSJed Brown /// " 101*c68be7a2SJeremy L Thompson /// ); 102*c68be7a2SJeremy L Thompson /// # Ok(()) 103*c68be7a2SJeremy L Thompson /// # } 1049df49d7eSJed Brown /// ``` 1059df49d7eSJed Brown fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1069df49d7eSJed Brown let mut ptr = std::ptr::null_mut(); 1079df49d7eSJed Brown let mut sizeloc = crate::MAX_BUFFER_LENGTH; 1089df49d7eSJed Brown let format = CString::new("%12.8f").expect("CString::new failed"); 1099df49d7eSJed Brown let format_c: *const c_char = format.into_raw(); 1109df49d7eSJed Brown let cstring = unsafe { 1119df49d7eSJed Brown let file = bind_ceed::open_memstream(&mut ptr, &mut sizeloc); 1129df49d7eSJed Brown bind_ceed::CeedVectorView(self.ptr, format_c, file); 1139df49d7eSJed Brown bind_ceed::fclose(file); 1149df49d7eSJed Brown CString::from_raw(ptr) 1159df49d7eSJed Brown }; 1169df49d7eSJed Brown cstring.to_string_lossy().fmt(f) 1179df49d7eSJed Brown } 1189df49d7eSJed Brown } 1199df49d7eSJed Brown 1209df49d7eSJed Brown // ----------------------------------------------------------------------------- 1219df49d7eSJed Brown // Implementations 1229df49d7eSJed Brown // ----------------------------------------------------------------------------- 1239df49d7eSJed Brown impl<'a> Vector<'a> { 1249df49d7eSJed Brown // Constructors 1259df49d7eSJed Brown pub fn create(ceed: &'a crate::Ceed, n: usize) -> crate::Result<Self> { 1269df49d7eSJed Brown let n = i32::try_from(n).unwrap(); 1279df49d7eSJed Brown let mut ptr = std::ptr::null_mut(); 1289df49d7eSJed Brown let ierr = unsafe { bind_ceed::CeedVectorCreate(ceed.ptr, n, &mut ptr) }; 1299df49d7eSJed Brown ceed.check_error(ierr)?; 1309df49d7eSJed Brown Ok(Self { ceed, ptr }) 1319df49d7eSJed Brown } 1329df49d7eSJed Brown 1339df49d7eSJed Brown pub(crate) fn from_raw( 1349df49d7eSJed Brown ceed: &'a crate::Ceed, 1359df49d7eSJed Brown ptr: bind_ceed::CeedVector, 1369df49d7eSJed Brown ) -> crate::Result<Self> { 1379df49d7eSJed Brown Ok(Self { ceed, ptr }) 1389df49d7eSJed Brown } 1399df49d7eSJed Brown 1409df49d7eSJed Brown /// Create a Vector from a slice 1419df49d7eSJed Brown /// 1429df49d7eSJed Brown /// # arguments 1439df49d7eSJed Brown /// 1449df49d7eSJed Brown /// * `slice` - values to initialize vector with 1459df49d7eSJed Brown /// 1469df49d7eSJed Brown /// ``` 1479df49d7eSJed Brown /// # use libceed::prelude::*; 148*c68be7a2SJeremy L Thompson /// # fn main() -> Result<(), libceed::CeedError> { 1499df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 150*c68be7a2SJeremy L Thompson /// let vec = vector::Vector::from_slice(&ceed, &[1., 2., 3.])?; 1519df49d7eSJed Brown /// assert_eq!(vec.length(), 3, "Incorrect length from slice"); 152*c68be7a2SJeremy L Thompson /// # Ok(()) 153*c68be7a2SJeremy L Thompson /// # } 1549df49d7eSJed Brown /// ``` 15580a9ef05SNatalie Beams pub fn from_slice(ceed: &'a crate::Ceed, v: &[crate::Scalar]) -> crate::Result<Self> { 1569df49d7eSJed Brown let mut x = Self::create(ceed, v.len())?; 1579df49d7eSJed Brown x.set_slice(v)?; 1589df49d7eSJed Brown Ok(x) 1599df49d7eSJed Brown } 1609df49d7eSJed Brown 1619df49d7eSJed Brown /// Create a Vector from a mutable array reference 1629df49d7eSJed Brown /// 1639df49d7eSJed Brown /// # arguments 1649df49d7eSJed Brown /// 1659df49d7eSJed Brown /// * `slice` - values to initialize vector with 1669df49d7eSJed Brown /// 1679df49d7eSJed Brown /// ``` 1689df49d7eSJed Brown /// # use libceed::prelude::*; 169*c68be7a2SJeremy L Thompson /// # fn main() -> Result<(), libceed::CeedError> { 1709df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 1719df49d7eSJed Brown /// let mut rust_vec = vec![1., 2., 3.]; 172*c68be7a2SJeremy L Thompson /// let vec = libceed::vector::Vector::from_array(&ceed, &mut rust_vec)?; 1739df49d7eSJed Brown /// 1749df49d7eSJed Brown /// assert_eq!(vec.length(), 3, "Incorrect length from slice"); 175*c68be7a2SJeremy L Thompson /// # Ok(()) 176*c68be7a2SJeremy L Thompson /// # } 1779df49d7eSJed Brown /// ``` 17880a9ef05SNatalie Beams pub fn from_array(ceed: &'a crate::Ceed, v: &mut [crate::Scalar]) -> crate::Result<Self> { 1799df49d7eSJed Brown let x = Self::create(ceed, v.len())?; 1809df49d7eSJed Brown let (host, user_pointer) = ( 1819df49d7eSJed Brown crate::MemType::Host as bind_ceed::CeedMemType, 1829df49d7eSJed Brown crate::CopyMode::UsePointer as bind_ceed::CeedCopyMode, 1839df49d7eSJed Brown ); 18480a9ef05SNatalie Beams let v = v.as_ptr() as *mut crate::Scalar; 1859df49d7eSJed Brown let ierr = unsafe { bind_ceed::CeedVectorSetArray(x.ptr, host, user_pointer, v) }; 1869df49d7eSJed Brown ceed.check_error(ierr)?; 1879df49d7eSJed Brown Ok(x) 1889df49d7eSJed Brown } 1899df49d7eSJed Brown 1909df49d7eSJed Brown /// Returns the length of a CeedVector 1919df49d7eSJed Brown /// 1929df49d7eSJed Brown /// ``` 1939df49d7eSJed Brown /// # use libceed::prelude::*; 194*c68be7a2SJeremy L Thompson /// # fn main() -> Result<(), libceed::CeedError> { 1959df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 196*c68be7a2SJeremy L Thompson /// let vec = ceed.vector(10)?; 1979df49d7eSJed Brown /// 1989df49d7eSJed Brown /// let n = vec.length(); 1999df49d7eSJed Brown /// assert_eq!(n, 10, "Incorrect length"); 200*c68be7a2SJeremy L Thompson /// # Ok(()) 201*c68be7a2SJeremy L Thompson /// # } 2029df49d7eSJed Brown /// ``` 2039df49d7eSJed Brown pub fn length(&self) -> usize { 2049df49d7eSJed Brown let mut n = 0; 2059df49d7eSJed Brown unsafe { bind_ceed::CeedVectorGetLength(self.ptr, &mut n) }; 2069df49d7eSJed Brown usize::try_from(n).unwrap() 2079df49d7eSJed Brown } 2089df49d7eSJed Brown 2099df49d7eSJed Brown /// Returns the length of a CeedVector 2109df49d7eSJed Brown /// 2119df49d7eSJed Brown /// ``` 2129df49d7eSJed Brown /// # use libceed::prelude::*; 213*c68be7a2SJeremy L Thompson /// # fn main() -> Result<(), libceed::CeedError> { 2149df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 215*c68be7a2SJeremy L Thompson /// let vec = ceed.vector(10)?; 2169df49d7eSJed Brown /// assert_eq!(vec.len(), 10, "Incorrect length"); 217*c68be7a2SJeremy L Thompson /// # Ok(()) 218*c68be7a2SJeremy L Thompson /// # } 2199df49d7eSJed Brown /// ``` 2209df49d7eSJed Brown pub fn len(&self) -> usize { 2219df49d7eSJed Brown self.length() 2229df49d7eSJed Brown } 2239df49d7eSJed Brown 2249df49d7eSJed Brown /// Set the CeedVector to a constant value 2259df49d7eSJed Brown /// 2269df49d7eSJed Brown /// # arguments 2279df49d7eSJed Brown /// 2289df49d7eSJed Brown /// * `val` - Value to be used 2299df49d7eSJed Brown /// 2309df49d7eSJed Brown /// ``` 2319df49d7eSJed Brown /// # use libceed::prelude::*; 232*c68be7a2SJeremy L Thompson /// # fn main() -> Result<(), libceed::CeedError> { 2339df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 2349df49d7eSJed Brown /// let len = 10; 235*c68be7a2SJeremy L Thompson /// let mut vec = ceed.vector(len)?; 2369df49d7eSJed Brown /// 2379df49d7eSJed Brown /// let val = 42.0; 238*c68be7a2SJeremy L Thompson /// vec.set_value(val)?; 2399df49d7eSJed Brown /// 2409df49d7eSJed Brown /// vec.view().iter().for_each(|v| { 2419df49d7eSJed Brown /// assert_eq!(*v, val, "Value not set correctly"); 2429df49d7eSJed Brown /// }); 243*c68be7a2SJeremy L Thompson /// # Ok(()) 244*c68be7a2SJeremy L Thompson /// # } 2459df49d7eSJed Brown /// ``` 24680a9ef05SNatalie Beams pub fn set_value(&mut self, value: crate::Scalar) -> crate::Result<i32> { 2479df49d7eSJed Brown let ierr = unsafe { bind_ceed::CeedVectorSetValue(self.ptr, value) }; 2489df49d7eSJed Brown self.ceed.check_error(ierr) 2499df49d7eSJed Brown } 2509df49d7eSJed Brown 2519df49d7eSJed Brown /// Set values from a slice of the same length 2529df49d7eSJed Brown /// 2539df49d7eSJed Brown /// # arguments 2549df49d7eSJed Brown /// 2559df49d7eSJed Brown /// * `slice` - values to into self; length must match 2569df49d7eSJed Brown /// 2579df49d7eSJed Brown /// ``` 2589df49d7eSJed Brown /// # use libceed::prelude::*; 259*c68be7a2SJeremy L Thompson /// # fn main() -> Result<(), libceed::CeedError> { 2609df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 261*c68be7a2SJeremy L Thompson /// let mut vec = ceed.vector(4)?; 262*c68be7a2SJeremy L Thompson /// vec.set_slice(&[10., 11., 12., 13.])?; 2639df49d7eSJed Brown /// 2649df49d7eSJed Brown /// vec.view().iter().enumerate().for_each(|(i, v)| { 26580a9ef05SNatalie Beams /// assert_eq!(*v, 10. + i as Scalar, "Slice not set correctly"); 2669df49d7eSJed Brown /// }); 267*c68be7a2SJeremy L Thompson /// # Ok(()) 268*c68be7a2SJeremy L Thompson /// # } 2699df49d7eSJed Brown /// ``` 27080a9ef05SNatalie Beams pub fn set_slice(&mut self, slice: &[crate::Scalar]) -> crate::Result<i32> { 2719df49d7eSJed Brown assert_eq!(self.length(), slice.len()); 2729df49d7eSJed Brown let (host, copy_mode) = ( 2739df49d7eSJed Brown crate::MemType::Host as bind_ceed::CeedMemType, 2749df49d7eSJed Brown crate::CopyMode::CopyValues as bind_ceed::CeedCopyMode, 2759df49d7eSJed Brown ); 2769df49d7eSJed Brown let ierr = unsafe { 27780a9ef05SNatalie Beams bind_ceed::CeedVectorSetArray( 27880a9ef05SNatalie Beams self.ptr, 27980a9ef05SNatalie Beams host, 28080a9ef05SNatalie Beams copy_mode, 28180a9ef05SNatalie Beams slice.as_ptr() as *mut crate::Scalar, 28280a9ef05SNatalie Beams ) 2839df49d7eSJed Brown }; 2849df49d7eSJed Brown self.ceed.check_error(ierr) 2859df49d7eSJed Brown } 2869df49d7eSJed Brown 2879df49d7eSJed Brown /// Sync the CeedVector to a specified memtype 2889df49d7eSJed Brown /// 2899df49d7eSJed Brown /// # arguments 2909df49d7eSJed Brown /// 2919df49d7eSJed Brown /// * `mtype` - Memtype to be synced 2929df49d7eSJed Brown /// 2939df49d7eSJed Brown /// ``` 2949df49d7eSJed Brown /// # use libceed::prelude::*; 295*c68be7a2SJeremy L Thompson /// # fn main() -> Result<(), libceed::CeedError> { 2969df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 2979df49d7eSJed Brown /// let len = 10; 298*c68be7a2SJeremy L Thompson /// let mut vec = ceed.vector(len)?; 2999df49d7eSJed Brown /// 3009df49d7eSJed Brown /// let val = 42.0; 3019df49d7eSJed Brown /// vec.set_value(val); 302*c68be7a2SJeremy L Thompson /// vec.sync(MemType::Host)?; 3039df49d7eSJed Brown /// 3049df49d7eSJed Brown /// vec.view().iter().for_each(|v| { 3059df49d7eSJed Brown /// assert_eq!(*v, val, "Value not set correctly"); 3069df49d7eSJed Brown /// }); 307*c68be7a2SJeremy L Thompson /// # Ok(()) 308*c68be7a2SJeremy L Thompson /// # } 3099df49d7eSJed Brown /// ``` 3109df49d7eSJed Brown pub fn sync(&self, mtype: crate::MemType) -> crate::Result<i32> { 3119df49d7eSJed Brown let ierr = 3129df49d7eSJed Brown unsafe { bind_ceed::CeedVectorSyncArray(self.ptr, mtype as bind_ceed::CeedMemType) }; 3139df49d7eSJed Brown self.ceed.check_error(ierr) 3149df49d7eSJed Brown } 3159df49d7eSJed Brown 3169df49d7eSJed Brown /// Create an immutable view 3179df49d7eSJed Brown /// 3189df49d7eSJed Brown /// ``` 3199df49d7eSJed Brown /// # use libceed::prelude::*; 320*c68be7a2SJeremy L Thompson /// # fn main() -> Result<(), libceed::CeedError> { 3219df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 322*c68be7a2SJeremy L Thompson /// let vec = ceed.vector_from_slice(&[10., 11., 12., 13.])?; 3239df49d7eSJed Brown /// 3249df49d7eSJed Brown /// let v = vec.view(); 3259df49d7eSJed Brown /// assert_eq!(v[0..2], [10., 11.]); 3269df49d7eSJed Brown /// 3279df49d7eSJed Brown /// // It is valid to have multiple immutable views 3289df49d7eSJed Brown /// let w = vec.view(); 3299df49d7eSJed Brown /// assert_eq!(v[1..], w[1..]); 330*c68be7a2SJeremy L Thompson /// # Ok(()) 331*c68be7a2SJeremy L Thompson /// # } 3329df49d7eSJed Brown /// ``` 3339df49d7eSJed Brown pub fn view(&self) -> VectorView { 3349df49d7eSJed Brown VectorView::new(self) 3359df49d7eSJed Brown } 3369df49d7eSJed Brown 3379df49d7eSJed Brown /// Create an mutable view 3389df49d7eSJed Brown /// 3399df49d7eSJed Brown /// ``` 3409df49d7eSJed Brown /// # use libceed::prelude::*; 341*c68be7a2SJeremy L Thompson /// # fn main() -> Result<(), libceed::CeedError> { 3429df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 343*c68be7a2SJeremy L Thompson /// let mut vec = ceed.vector_from_slice(&[10., 11., 12., 13.])?; 3449df49d7eSJed Brown /// 3459df49d7eSJed Brown /// { 3469df49d7eSJed Brown /// let mut v = vec.view_mut(); 3479df49d7eSJed Brown /// v[2] = 9.; 3489df49d7eSJed Brown /// } 3499df49d7eSJed Brown /// 3509df49d7eSJed Brown /// let w = vec.view(); 3519df49d7eSJed Brown /// assert_eq!(w[2], 9., "View did not mutate data"); 352*c68be7a2SJeremy L Thompson /// # Ok(()) 353*c68be7a2SJeremy L Thompson /// # } 3549df49d7eSJed Brown /// ``` 3559df49d7eSJed Brown pub fn view_mut(&mut self) -> VectorViewMut { 3569df49d7eSJed Brown VectorViewMut::new(self) 3579df49d7eSJed Brown } 3589df49d7eSJed Brown 3599df49d7eSJed Brown /// Return the norm of a CeedVector 3609df49d7eSJed Brown /// 3619df49d7eSJed Brown /// # arguments 3629df49d7eSJed Brown /// 3639df49d7eSJed Brown /// * `ntype` - Norm type One, Two, or Max 3649df49d7eSJed Brown /// 3659df49d7eSJed Brown /// ``` 3669df49d7eSJed Brown /// # use libceed::prelude::*; 367*c68be7a2SJeremy L Thompson /// # fn main() -> Result<(), libceed::CeedError> { 3689df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 369*c68be7a2SJeremy L Thompson /// let vec = ceed.vector_from_slice(&[1., 2., 3., 4.])?; 3709df49d7eSJed Brown /// 371*c68be7a2SJeremy L Thompson /// let max_norm = vec.norm(NormType::Max)?; 3729df49d7eSJed Brown /// assert_eq!(max_norm, 4.0, "Incorrect Max norm"); 3739df49d7eSJed Brown /// 374*c68be7a2SJeremy L Thompson /// let l1_norm = vec.norm(NormType::One)?; 3759df49d7eSJed Brown /// assert_eq!(l1_norm, 10., "Incorrect L1 norm"); 3769df49d7eSJed Brown /// 377*c68be7a2SJeremy L Thompson /// let l2_norm = vec.norm(NormType::Two)?; 3789df49d7eSJed Brown /// assert!((l2_norm - 5.477) < 1e-3, "Incorrect L2 norm"); 379*c68be7a2SJeremy L Thompson /// # Ok(()) 380*c68be7a2SJeremy L Thompson /// # } 3819df49d7eSJed Brown /// ``` 38280a9ef05SNatalie Beams pub fn norm(&self, ntype: crate::NormType) -> crate::Result<crate::Scalar> { 38380a9ef05SNatalie Beams let mut res: crate::Scalar = 0.0; 3849df49d7eSJed Brown let ierr = unsafe { 3859df49d7eSJed Brown bind_ceed::CeedVectorNorm(self.ptr, ntype as bind_ceed::CeedNormType, &mut res) 3869df49d7eSJed Brown }; 3879df49d7eSJed Brown self.ceed.check_error(ierr)?; 3889df49d7eSJed Brown Ok(res) 3899df49d7eSJed Brown } 3909df49d7eSJed Brown 3919df49d7eSJed Brown /// Compute x = alpha x for a CeedVector 3929df49d7eSJed Brown /// 3939df49d7eSJed Brown /// # arguments 3949df49d7eSJed Brown /// 3959df49d7eSJed Brown /// * `alpha` - scaling factor 3969df49d7eSJed Brown /// 3979df49d7eSJed Brown /// ``` 3989df49d7eSJed Brown /// # use libceed::prelude::*; 399*c68be7a2SJeremy L Thompson /// # fn main() -> Result<(), libceed::CeedError> { 4009df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 401*c68be7a2SJeremy L Thompson /// let mut vec = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?; 4029df49d7eSJed Brown /// 403*c68be7a2SJeremy L Thompson /// vec = vec.scale(-1.0)?; 4049df49d7eSJed Brown /// vec.view().iter().enumerate().for_each(|(i, &v)| { 40580a9ef05SNatalie Beams /// assert_eq!(v, -(i as Scalar), "Value not set correctly"); 4069df49d7eSJed Brown /// }); 407*c68be7a2SJeremy L Thompson /// # Ok(()) 408*c68be7a2SJeremy L Thompson /// # } 4099df49d7eSJed Brown /// ``` 4109df49d7eSJed Brown #[allow(unused_mut)] 41180a9ef05SNatalie Beams pub fn scale(mut self, alpha: crate::Scalar) -> crate::Result<Self> { 4129df49d7eSJed Brown let ierr = unsafe { bind_ceed::CeedVectorScale(self.ptr, alpha) }; 4139df49d7eSJed Brown self.ceed.check_error(ierr)?; 4149df49d7eSJed Brown Ok(self) 4159df49d7eSJed Brown } 4169df49d7eSJed Brown 4179df49d7eSJed Brown /// Compute y = alpha x + y for a pair of CeedVectors 4189df49d7eSJed Brown /// 4199df49d7eSJed Brown /// # arguments 4209df49d7eSJed Brown /// 4219df49d7eSJed Brown /// * `alpha` - scaling factor 4229df49d7eSJed Brown /// * `x` - second vector, must be different than self 4239df49d7eSJed Brown /// 4249df49d7eSJed Brown /// ``` 4259df49d7eSJed Brown /// # use libceed::prelude::*; 426*c68be7a2SJeremy L Thompson /// # fn main() -> Result<(), libceed::CeedError> { 4279df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 428*c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?; 429*c68be7a2SJeremy L Thompson /// let mut y = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?; 4309df49d7eSJed Brown /// 431*c68be7a2SJeremy L Thompson /// y = y.axpy(-0.5, &x)?; 4329df49d7eSJed Brown /// y.view().iter().enumerate().for_each(|(i, &v)| { 43380a9ef05SNatalie Beams /// assert_eq!(v, (i as Scalar) / 2.0, "Value not set correctly"); 4349df49d7eSJed Brown /// }); 435*c68be7a2SJeremy L Thompson /// # Ok(()) 436*c68be7a2SJeremy L Thompson /// # } 4379df49d7eSJed Brown /// ``` 4389df49d7eSJed Brown #[allow(unused_mut)] 43980a9ef05SNatalie Beams pub fn axpy(mut self, alpha: crate::Scalar, x: &crate::Vector) -> crate::Result<Self> { 4409df49d7eSJed Brown let ierr = unsafe { bind_ceed::CeedVectorAXPY(self.ptr, alpha, x.ptr) }; 4419df49d7eSJed Brown self.ceed.check_error(ierr)?; 4429df49d7eSJed Brown Ok(self) 4439df49d7eSJed Brown } 4449df49d7eSJed Brown 4459df49d7eSJed Brown /// Compute the pointwise multiplication w = x .* y for CeedVectors 4469df49d7eSJed Brown /// 4479df49d7eSJed Brown /// # arguments 4489df49d7eSJed Brown /// 4499df49d7eSJed Brown /// * `x` - first vector for product 4509df49d7eSJed Brown /// * `y` - second vector for product 4519df49d7eSJed Brown /// 4529df49d7eSJed Brown /// ``` 4539df49d7eSJed Brown /// # use libceed::prelude::*; 454*c68be7a2SJeremy L Thompson /// # fn main() -> Result<(), libceed::CeedError> { 4559df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 456*c68be7a2SJeremy L Thompson /// let mut w = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?; 457*c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?; 458*c68be7a2SJeremy L Thompson /// let y = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?; 4599df49d7eSJed Brown /// 460*c68be7a2SJeremy L Thompson /// w = w.pointwise_mult(&x, &y)?; 4619df49d7eSJed Brown /// w.view().iter().enumerate().for_each(|(i, &v)| { 46280a9ef05SNatalie Beams /// assert_eq!(v, (i as Scalar).powf(2.0), "Value not set correctly"); 4639df49d7eSJed Brown /// }); 464*c68be7a2SJeremy L Thompson /// # Ok(()) 465*c68be7a2SJeremy L Thompson /// # } 4669df49d7eSJed Brown /// ``` 4679df49d7eSJed Brown #[allow(unused_mut)] 4689df49d7eSJed Brown pub fn pointwise_mult(mut self, x: &crate::Vector, y: &crate::Vector) -> crate::Result<Self> { 4699df49d7eSJed Brown let ierr = unsafe { bind_ceed::CeedVectorPointwiseMult(self.ptr, x.ptr, y.ptr) }; 4709df49d7eSJed Brown self.ceed.check_error(ierr)?; 4719df49d7eSJed Brown Ok(self) 4729df49d7eSJed Brown } 4739df49d7eSJed Brown 4749df49d7eSJed Brown /// Compute the pointwise multiplication w = w .* x for CeedVectors 4759df49d7eSJed Brown /// 4769df49d7eSJed Brown /// # arguments 4779df49d7eSJed Brown /// 4789df49d7eSJed Brown /// * `x` - second vector for product 4799df49d7eSJed Brown /// 4809df49d7eSJed Brown /// ``` 4819df49d7eSJed Brown /// # use libceed::prelude::*; 482*c68be7a2SJeremy L Thompson /// # fn main() -> Result<(), libceed::CeedError> { 4839df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 484*c68be7a2SJeremy L Thompson /// let mut w = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?; 485*c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?; 4869df49d7eSJed Brown /// 487*c68be7a2SJeremy L Thompson /// w = w.pointwise_scale(&x)?; 4889df49d7eSJed Brown /// w.view().iter().enumerate().for_each(|(i, &v)| { 48980a9ef05SNatalie Beams /// assert_eq!(v, (i as Scalar).powf(2.0), "Value not set correctly"); 4909df49d7eSJed Brown /// }); 491*c68be7a2SJeremy L Thompson /// # Ok(()) 492*c68be7a2SJeremy L Thompson /// # } 4939df49d7eSJed Brown /// ``` 4949df49d7eSJed Brown #[allow(unused_mut)] 4959df49d7eSJed Brown pub fn pointwise_scale(mut self, x: &crate::Vector) -> crate::Result<Self> { 4969df49d7eSJed Brown let ierr = unsafe { bind_ceed::CeedVectorPointwiseMult(self.ptr, self.ptr, x.ptr) }; 4979df49d7eSJed Brown self.ceed.check_error(ierr)?; 4989df49d7eSJed Brown Ok(self) 4999df49d7eSJed Brown } 5009df49d7eSJed Brown 5019df49d7eSJed Brown /// Compute the pointwise multiplication w = w .* w for a CeedVector 5029df49d7eSJed Brown /// 5039df49d7eSJed Brown /// ``` 5049df49d7eSJed Brown /// # use libceed::prelude::*; 505*c68be7a2SJeremy L Thompson /// # fn main() -> Result<(), libceed::CeedError> { 5069df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 507*c68be7a2SJeremy L Thompson /// let mut w = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?; 5089df49d7eSJed Brown /// 509*c68be7a2SJeremy L Thompson /// w = w.pointwise_square()?; 5109df49d7eSJed Brown /// w.view().iter().enumerate().for_each(|(i, &v)| { 51180a9ef05SNatalie Beams /// assert_eq!(v, (i as Scalar).powf(2.0), "Value not set correctly"); 5129df49d7eSJed Brown /// }); 513*c68be7a2SJeremy L Thompson /// # Ok(()) 514*c68be7a2SJeremy L Thompson /// # } 5159df49d7eSJed Brown /// ``` 5169df49d7eSJed Brown #[allow(unused_mut)] 5179df49d7eSJed Brown pub fn pointwise_square(mut self) -> crate::Result<Self> { 5189df49d7eSJed Brown let ierr = unsafe { bind_ceed::CeedVectorPointwiseMult(self.ptr, self.ptr, self.ptr) }; 5199df49d7eSJed Brown self.ceed.check_error(ierr)?; 5209df49d7eSJed Brown Ok(self) 5219df49d7eSJed Brown } 5229df49d7eSJed Brown } 5239df49d7eSJed Brown 5249df49d7eSJed Brown // ----------------------------------------------------------------------------- 5259df49d7eSJed Brown // Vector Viewer 5269df49d7eSJed Brown // ----------------------------------------------------------------------------- 5279df49d7eSJed Brown /// A (host) view of a Vector with Deref to slice. We can't make 5289df49d7eSJed Brown /// Vector itself Deref to slice because we can't handle the drop to 5299df49d7eSJed Brown /// call bind_ceed::CeedVectorRestoreArrayRead(). 5309df49d7eSJed Brown #[derive(Debug)] 5319df49d7eSJed Brown pub struct VectorView<'a> { 5329df49d7eSJed Brown vec: &'a Vector<'a>, 53380a9ef05SNatalie Beams array: *const crate::Scalar, 5349df49d7eSJed Brown } 5359df49d7eSJed Brown 5369df49d7eSJed Brown impl<'a> VectorView<'a> { 5379df49d7eSJed Brown /// Construct a VectorView from a Vector reference 5389df49d7eSJed Brown fn new(vec: &'a Vector) -> Self { 5399df49d7eSJed Brown let mut array = std::ptr::null(); 5409df49d7eSJed Brown unsafe { 5419df49d7eSJed Brown bind_ceed::CeedVectorGetArrayRead( 5429df49d7eSJed Brown vec.ptr, 5439df49d7eSJed Brown crate::MemType::Host as bind_ceed::CeedMemType, 5449df49d7eSJed Brown &mut array, 5459df49d7eSJed Brown ); 5469df49d7eSJed Brown } 5479df49d7eSJed Brown Self { 5489df49d7eSJed Brown vec: vec, 5499df49d7eSJed Brown array: array, 5509df49d7eSJed Brown } 5519df49d7eSJed Brown } 5529df49d7eSJed Brown } 5539df49d7eSJed Brown 5549df49d7eSJed Brown // Destructor 5559df49d7eSJed Brown impl<'a> Drop for VectorView<'a> { 5569df49d7eSJed Brown fn drop(&mut self) { 5579df49d7eSJed Brown unsafe { 5589df49d7eSJed Brown bind_ceed::CeedVectorRestoreArrayRead(self.vec.ptr, &mut self.array); 5599df49d7eSJed Brown } 5609df49d7eSJed Brown } 5619df49d7eSJed Brown } 5629df49d7eSJed Brown 5639df49d7eSJed Brown // Data access 5649df49d7eSJed Brown impl<'a> Deref for VectorView<'a> { 56580a9ef05SNatalie Beams type Target = [crate::Scalar]; 56680a9ef05SNatalie Beams fn deref(&self) -> &[crate::Scalar] { 5679df49d7eSJed Brown unsafe { std::slice::from_raw_parts(self.array, self.vec.len()) } 5689df49d7eSJed Brown } 5699df49d7eSJed Brown } 5709df49d7eSJed Brown 5719df49d7eSJed Brown // Viewing 5729df49d7eSJed Brown impl<'a> fmt::Display for VectorView<'a> { 5739df49d7eSJed Brown fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 5749df49d7eSJed Brown write!(f, "VectorView({:?})", self.deref()) 5759df49d7eSJed Brown } 5769df49d7eSJed Brown } 5779df49d7eSJed Brown 5789df49d7eSJed Brown // ----------------------------------------------------------------------------- 5799df49d7eSJed Brown // Vector Viewer Mutable 5809df49d7eSJed Brown // ----------------------------------------------------------------------------- 5819df49d7eSJed Brown /// A mutable (host) view of a Vector with Deref to slice. 5829df49d7eSJed Brown #[derive(Debug)] 5839df49d7eSJed Brown pub struct VectorViewMut<'a> { 5849df49d7eSJed Brown vec: &'a Vector<'a>, 58580a9ef05SNatalie Beams array: *mut crate::Scalar, 5869df49d7eSJed Brown } 5879df49d7eSJed Brown 5889df49d7eSJed Brown impl<'a> VectorViewMut<'a> { 5899df49d7eSJed Brown /// Construct a VectorViewMut from a Vector reference 5909df49d7eSJed Brown fn new(vec: &'a mut Vector) -> Self { 5919df49d7eSJed Brown let mut ptr = std::ptr::null_mut(); 5929df49d7eSJed Brown unsafe { 5939df49d7eSJed Brown bind_ceed::CeedVectorGetArray( 5949df49d7eSJed Brown vec.ptr, 5959df49d7eSJed Brown crate::MemType::Host as bind_ceed::CeedMemType, 5969df49d7eSJed Brown &mut ptr, 5979df49d7eSJed Brown ); 5989df49d7eSJed Brown } 5999df49d7eSJed Brown Self { 6009df49d7eSJed Brown vec: vec, 6019df49d7eSJed Brown array: ptr, 6029df49d7eSJed Brown } 6039df49d7eSJed Brown } 6049df49d7eSJed Brown } 6059df49d7eSJed Brown 6069df49d7eSJed Brown // Destructor 6079df49d7eSJed Brown impl<'a> Drop for VectorViewMut<'a> { 6089df49d7eSJed Brown fn drop(&mut self) { 6099df49d7eSJed Brown unsafe { 6109df49d7eSJed Brown bind_ceed::CeedVectorRestoreArray(self.vec.ptr, &mut self.array); 6119df49d7eSJed Brown } 6129df49d7eSJed Brown } 6139df49d7eSJed Brown } 6149df49d7eSJed Brown 6159df49d7eSJed Brown // Data access 6169df49d7eSJed Brown impl<'a> Deref for VectorViewMut<'a> { 61780a9ef05SNatalie Beams type Target = [crate::Scalar]; 61880a9ef05SNatalie Beams fn deref(&self) -> &[crate::Scalar] { 6199df49d7eSJed Brown unsafe { std::slice::from_raw_parts(self.array, self.vec.len()) } 6209df49d7eSJed Brown } 6219df49d7eSJed Brown } 6229df49d7eSJed Brown 6239df49d7eSJed Brown // Mutable data access 6249df49d7eSJed Brown impl<'a> DerefMut for VectorViewMut<'a> { 62580a9ef05SNatalie Beams fn deref_mut(&mut self) -> &mut [crate::Scalar] { 6269df49d7eSJed Brown unsafe { std::slice::from_raw_parts_mut(self.array, self.vec.len()) } 6279df49d7eSJed Brown } 6289df49d7eSJed Brown } 6299df49d7eSJed Brown 6309df49d7eSJed Brown // Viewing 6319df49d7eSJed Brown impl<'a> fmt::Display for VectorViewMut<'a> { 6329df49d7eSJed Brown fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 6339df49d7eSJed Brown write!(f, "VectorViewMut({:?})", self.deref()) 6349df49d7eSJed Brown } 6359df49d7eSJed Brown } 6369df49d7eSJed Brown 6379df49d7eSJed Brown // ----------------------------------------------------------------------------- 638