xref: /libCEED/rust/libceed/src/vector.rs (revision 486868d327245acbd632a21d6e4ba40bf77b926c)
1 // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3 // reserved. See files LICENSE and NOTICE for details.
4 //
5 // This file is part of CEED, a collection of benchmarks, miniapps, software
6 // libraries and APIs for efficient high-order finite element and spectral
7 // element discretizations for exascale applications. For more information and
8 // source code availability see http://github.com/ceed.
9 //
10 // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11 // a collaborative effort of two U.S. Department of Energy organizations (Office
12 // of Science and the National Nuclear Security Administration) responsible for
13 // the planning and preparation of a capable exascale ecosystem, including
14 // software, applications, hardware, advanced system engineering and early
15 // testbed platforms, in support of the nation's exascale computing imperative
16 
17 //! A Ceed Vector constitutes the main data structure and serves as input/output
18 //! for Ceed Operators.
19 
20 use std::{
21     ops::{Deref, DerefMut},
22     os::raw::c_char,
23 };
24 
25 use crate::prelude::*;
26 
27 // -----------------------------------------------------------------------------
28 // CeedVector option
29 // -----------------------------------------------------------------------------
30 #[derive(Debug)]
31 pub enum VectorOpt<'a> {
32     Some(&'a Vector<'a>),
33     Active,
34     None,
35 }
36 /// Construct a VectorOpt reference from a Vector reference
37 impl<'a> From<&'a Vector<'_>> for VectorOpt<'a> {
38     fn from(vec: &'a Vector) -> Self {
39         debug_assert!(vec.ptr != unsafe { bind_ceed::CEED_VECTOR_ACTIVE });
40         debug_assert!(vec.ptr != unsafe { bind_ceed::CEED_VECTOR_NONE });
41         Self::Some(vec)
42     }
43 }
44 impl<'a> VectorOpt<'a> {
45     /// Transform a Rust libCEED VectorOpt into C libCEED CeedVector
46     pub(crate) fn to_raw(self) -> bind_ceed::CeedVector {
47         match self {
48             Self::Some(vec) => vec.ptr,
49             Self::Active => unsafe { bind_ceed::CEED_VECTOR_ACTIVE },
50             Self::None => unsafe { bind_ceed::CEED_VECTOR_NONE },
51         }
52     }
53 
54     /// Check if a VectorOpt is Some
55     ///
56     /// ```
57     /// # use libceed::prelude::*;
58     /// # fn main() -> libceed::Result<()> {
59     /// # let ceed = libceed::Ceed::default_init();
60     /// let vec = libceed::vector::Vector::from_slice(&ceed, &[1., 2., 3.])?;
61     /// let vec_opt = VectorOpt::from(&vec);
62     /// assert!(vec_opt.is_some(), "Incorrect VectorOpt");
63     ///
64     /// let vec_opt = VectorOpt::Active;
65     /// assert!(!vec_opt.is_some(), "Incorrect VectorOpt");
66     ///
67     /// let vec_opt = VectorOpt::None;
68     /// assert!(!vec_opt.is_some(), "Incorrect VectorOpt");
69     /// # Ok(())
70     /// # }
71     /// ```
72     pub fn is_some(&self) -> bool {
73         match self {
74             Self::Some(_) => true,
75             Self::Active => false,
76             Self::None => false,
77         }
78     }
79 
80     /// Check if a VectorOpt is Active
81     ///
82     /// ```
83     /// # use libceed::prelude::*;
84     /// # fn main() -> libceed::Result<()> {
85     /// # let ceed = libceed::Ceed::default_init();
86     /// let vec = libceed::vector::Vector::from_slice(&ceed, &[1., 2., 3.])?;
87     /// let vec_opt = VectorOpt::from(&vec);
88     /// assert!(!vec_opt.is_active(), "Incorrect VectorOpt");
89     ///
90     /// let vec_opt = VectorOpt::Active;
91     /// assert!(vec_opt.is_active(), "Incorrect VectorOpt");
92     ///
93     /// let vec_opt = VectorOpt::None;
94     /// assert!(!vec_opt.is_active(), "Incorrect VectorOpt");
95     /// # Ok(())
96     /// # }
97     /// ```
98     pub fn is_active(&self) -> bool {
99         match self {
100             Self::Some(_) => false,
101             Self::Active => true,
102             Self::None => false,
103         }
104     }
105 
106     /// Check if a VectorOpt is Some
107     ///
108     /// ```
109     /// # use libceed::prelude::*;
110     /// # fn main() -> libceed::Result<()> {
111     /// # let ceed = libceed::Ceed::default_init();
112     /// let vec = libceed::vector::Vector::from_slice(&ceed, &[1., 2., 3.])?;
113     /// let vec_opt = VectorOpt::from(&vec);
114     /// assert!(!vec_opt.is_none(), "Incorrect VectorOpt");
115     ///
116     /// let vec_opt = VectorOpt::Active;
117     /// assert!(!vec_opt.is_none(), "Incorrect VectorOpt");
118     ///
119     /// let vec_opt = VectorOpt::None;
120     /// assert!(vec_opt.is_none(), "Incorrect VectorOpt");
121     /// # Ok(())
122     /// # }
123     /// ```
124     pub fn is_none(&self) -> bool {
125         match self {
126             Self::Some(_) => false,
127             Self::Active => false,
128             Self::None => true,
129         }
130     }
131 }
132 
133 // -----------------------------------------------------------------------------
134 // CeedVector borrowed slice wrapper
135 // -----------------------------------------------------------------------------
136 pub struct VectorSliceWrapper<'a> {
137     pub(crate) vector: crate::Vector<'a>,
138     pub(crate) _slice: &'a mut [crate::Scalar],
139 }
140 
141 // -----------------------------------------------------------------------------
142 // Destructor
143 // -----------------------------------------------------------------------------
144 impl<'a> Drop for VectorSliceWrapper<'a> {
145     fn drop(&mut self) {
146         unsafe {
147             bind_ceed::CeedVectorTakeArray(
148                 self.vector.ptr,
149                 crate::MemType::Host as bind_ceed::CeedMemType,
150                 std::ptr::null_mut(),
151             )
152         };
153     }
154 }
155 
156 // -----------------------------------------------------------------------------
157 // CeedVector context wrapper
158 // -----------------------------------------------------------------------------
159 #[derive(Debug)]
160 pub struct Vector<'a> {
161     pub(crate) ptr: bind_ceed::CeedVector,
162     _lifeline: PhantomData<&'a ()>,
163 }
164 impl From<&'_ Vector<'_>> for bind_ceed::CeedVector {
165     fn from(vec: &Vector) -> Self {
166         vec.ptr
167     }
168 }
169 
170 // -----------------------------------------------------------------------------
171 // Destructor
172 // -----------------------------------------------------------------------------
173 impl<'a> Drop for Vector<'a> {
174     fn drop(&mut self) {
175         let not_none_and_active = self.ptr != unsafe { bind_ceed::CEED_VECTOR_NONE }
176             && self.ptr != unsafe { bind_ceed::CEED_VECTOR_ACTIVE };
177 
178         if not_none_and_active {
179             unsafe { bind_ceed::CeedVectorDestroy(&mut self.ptr) };
180         }
181     }
182 }
183 
184 // -----------------------------------------------------------------------------
185 // Display
186 // -----------------------------------------------------------------------------
187 impl<'a> fmt::Display for Vector<'a> {
188     /// View a Vector
189     ///
190     /// ```
191     /// # use libceed::prelude::*;
192     /// # fn main() -> libceed::Result<()> {
193     /// # let ceed = libceed::Ceed::default_init();
194     /// let vec = libceed::vector::Vector::from_slice(&ceed, &[1., 2., 3.])?;
195     /// assert_eq!(
196     ///     vec.to_string(),
197     ///     "CeedVector length 3
198     ///     1.00000000
199     ///     2.00000000
200     ///     3.00000000
201     /// "
202     /// );
203     /// # Ok(())
204     /// # }
205     /// ```
206     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
207         let mut ptr = std::ptr::null_mut();
208         let mut sizeloc = crate::MAX_BUFFER_LENGTH;
209         let format = CString::new("%12.8f").expect("CString::new failed");
210         let format_c: *const c_char = format.into_raw();
211         let cstring = unsafe {
212             let file = bind_ceed::open_memstream(&mut ptr, &mut sizeloc);
213             bind_ceed::CeedVectorView(self.ptr, format_c, file);
214             bind_ceed::fclose(file);
215             CString::from_raw(ptr)
216         };
217         cstring.to_string_lossy().fmt(f)
218     }
219 }
220 
221 // -----------------------------------------------------------------------------
222 // Implementations
223 // -----------------------------------------------------------------------------
224 impl<'a> Vector<'a> {
225     // Constructors
226     pub fn create(ceed: &'a crate::Ceed, n: usize) -> crate::Result<Self> {
227         let n = i32::try_from(n).unwrap();
228         let mut ptr = std::ptr::null_mut();
229         let ierr = unsafe { bind_ceed::CeedVectorCreate(ceed.ptr, n, &mut ptr) };
230         ceed.check_error(ierr)?;
231         Ok(Self {
232             ptr,
233             _lifeline: PhantomData,
234         })
235     }
236 
237     pub(crate) fn from_raw(ptr: bind_ceed::CeedVector) -> crate::Result<Self> {
238         Ok(Self {
239             ptr,
240             _lifeline: PhantomData,
241         })
242     }
243 
244     /// Create a Vector from a slice
245     ///
246     /// # arguments
247     ///
248     /// * `slice` - values to initialize vector with
249     ///
250     /// ```
251     /// # use libceed::prelude::*;
252     /// # fn main() -> libceed::Result<()> {
253     /// # let ceed = libceed::Ceed::default_init();
254     /// let vec = vector::Vector::from_slice(&ceed, &[1., 2., 3.])?;
255     /// assert_eq!(vec.length(), 3, "Incorrect length from slice");
256     /// # Ok(())
257     /// # }
258     /// ```
259     pub fn from_slice(ceed: &'a crate::Ceed, v: &[crate::Scalar]) -> crate::Result<Self> {
260         let mut x = Self::create(ceed, v.len())?;
261         x.set_slice(v)?;
262         Ok(x)
263     }
264 
265     /// Create a Vector from a mutable array reference
266     ///
267     /// # arguments
268     ///
269     /// * `slice` - values to initialize vector with
270     ///
271     /// ```
272     /// # use libceed::prelude::*;
273     /// # fn main() -> libceed::Result<()> {
274     /// # let ceed = libceed::Ceed::default_init();
275     /// let mut rust_vec = vec![1., 2., 3.];
276     /// let vec = libceed::vector::Vector::from_array(&ceed, &mut rust_vec)?;
277     ///
278     /// assert_eq!(vec.length(), 3, "Incorrect length from slice");
279     /// # Ok(())
280     /// # }
281     /// ```
282     pub fn from_array(ceed: &'a crate::Ceed, v: &mut [crate::Scalar]) -> crate::Result<Self> {
283         let x = Self::create(ceed, v.len())?;
284         let (host, user_pointer) = (
285             crate::MemType::Host as bind_ceed::CeedMemType,
286             crate::CopyMode::UsePointer as bind_ceed::CeedCopyMode,
287         );
288         let v = v.as_ptr() as *mut crate::Scalar;
289         let ierr = unsafe { bind_ceed::CeedVectorSetArray(x.ptr, host, user_pointer, v) };
290         ceed.check_error(ierr)?;
291         Ok(x)
292     }
293 
294     // Error handling
295     #[doc(hidden)]
296     fn check_error(&self, ierr: i32) -> crate::Result<i32> {
297         let mut ptr = std::ptr::null_mut();
298         unsafe {
299             bind_ceed::CeedVectorGetCeed(self.ptr, &mut ptr);
300         }
301         crate::check_error(ptr, ierr)
302     }
303 
304     /// Returns the length of a CeedVector
305     ///
306     /// ```
307     /// # use libceed::prelude::*;
308     /// # fn main() -> libceed::Result<()> {
309     /// # let ceed = libceed::Ceed::default_init();
310     /// let vec = ceed.vector(10)?;
311     ///
312     /// let n = vec.length();
313     /// assert_eq!(n, 10, "Incorrect length");
314     /// # Ok(())
315     /// # }
316     /// ```
317     pub fn length(&self) -> usize {
318         let mut n = 0;
319         unsafe { bind_ceed::CeedVectorGetLength(self.ptr, &mut n) };
320         usize::try_from(n).unwrap()
321     }
322 
323     /// Returns the length of a CeedVector
324     ///
325     /// ```
326     /// # use libceed::prelude::*;
327     /// # fn main() -> libceed::Result<()> {
328     /// # let ceed = libceed::Ceed::default_init();
329     /// let vec = ceed.vector(10)?;
330     /// assert_eq!(vec.len(), 10, "Incorrect length");
331     /// # Ok(())
332     /// # }
333     /// ```
334     pub fn len(&self) -> usize {
335         self.length()
336     }
337 
338     /// Set the CeedVector to a constant value
339     ///
340     /// # arguments
341     ///
342     /// * `val` - Value to be used
343     ///
344     /// ```
345     /// # use libceed::prelude::*;
346     /// # fn main() -> libceed::Result<()> {
347     /// # let ceed = libceed::Ceed::default_init();
348     /// let len = 10;
349     /// let mut vec = ceed.vector(len)?;
350     ///
351     /// let val = 42.0;
352     /// vec.set_value(val)?;
353     ///
354     /// vec.view()?.iter().for_each(|v| {
355     ///     assert_eq!(*v, val, "Value not set correctly");
356     /// });
357     /// # Ok(())
358     /// # }
359     /// ```
360     pub fn set_value(&mut self, value: crate::Scalar) -> crate::Result<i32> {
361         let ierr = unsafe { bind_ceed::CeedVectorSetValue(self.ptr, value) };
362         self.check_error(ierr)
363     }
364 
365     /// Set values from a slice of the same length
366     ///
367     /// # arguments
368     ///
369     /// * `slice` - values to into self; length must match
370     ///
371     /// ```
372     /// # use libceed::prelude::*;
373     /// # fn main() -> libceed::Result<()> {
374     /// # let ceed = libceed::Ceed::default_init();
375     /// let mut vec = ceed.vector(4)?;
376     /// vec.set_slice(&[10., 11., 12., 13.])?;
377     ///
378     /// vec.view()?.iter().enumerate().for_each(|(i, v)| {
379     ///     assert_eq!(*v, 10. + i as Scalar, "Slice not set correctly");
380     /// });
381     /// # Ok(())
382     /// # }
383     /// ```
384     pub fn set_slice(&mut self, slice: &[crate::Scalar]) -> crate::Result<i32> {
385         assert_eq!(self.length(), slice.len());
386         let (host, copy_mode) = (
387             crate::MemType::Host as bind_ceed::CeedMemType,
388             crate::CopyMode::CopyValues as bind_ceed::CeedCopyMode,
389         );
390         let ierr = unsafe {
391             bind_ceed::CeedVectorSetArray(
392                 self.ptr,
393                 host,
394                 copy_mode,
395                 slice.as_ptr() as *mut crate::Scalar,
396             )
397         };
398         self.check_error(ierr)
399     }
400 
401     /// Wrap a mutable slice in a Vector of the same length
402     ///
403     /// # arguments
404     ///
405     /// * `slice` - values to wrap in self; length must match
406     ///
407     /// ```
408     /// # use libceed::prelude::*;
409     /// # fn main() -> libceed::Result<()> {
410     /// # let ceed = libceed::Ceed::default_init();
411     /// let mut vec = ceed.vector(4)?;
412     /// let mut array = [10., 11., 12., 13.];
413     ///
414     /// {
415     ///     // `wrapper` holds a mutable reference to the wrapped slice
416     ///     //   that is dropped when `wrapper` goes out of scope
417     ///     let wrapper = vec.wrap_slice_mut(&mut array)?;
418     ///     vec.view()?.iter().enumerate().for_each(|(i, v)| {
419     ///         assert_eq!(*v, 10. + i as Scalar, "Slice not set correctly");
420     ///     });
421     ///
422     ///     // This line will not compile, as the `wrapper` holds mutable
423     ///     //   access to the `array`
424     ///     // array[0] = 5.0;
425     ///
426     ///     // Changes here are reflected in the `array`
427     ///     vec.set_value(5.0)?;
428     ///     vec.view()?.iter().for_each(|v| {
429     ///         assert_eq!(*v, 5.0 as Scalar, "Value not set correctly");
430     ///     });
431     /// }
432     ///
433     /// // 'array' remains changed
434     /// array.iter().for_each(|v| {
435     ///     assert_eq!(*v, 5.0 as Scalar, "Array not mutated correctly");
436     /// });
437     ///
438     /// // While changes to `vec` no longer affect `array`
439     /// vec.set_value(6.0)?;
440     /// array.iter().for_each(|v| {
441     ///     assert_eq!(*v, 5.0 as Scalar, "Array mutated without permission");
442     /// });
443     /// # Ok(())
444     /// # }
445     /// ```
446     pub fn wrap_slice_mut<'b>(
447         &mut self,
448         slice: &'b mut [crate::Scalar],
449     ) -> crate::Result<VectorSliceWrapper<'b>> {
450         assert_eq!(self.length(), slice.len());
451         let (host, copy_mode) = (
452             crate::MemType::Host as bind_ceed::CeedMemType,
453             crate::CopyMode::UsePointer as bind_ceed::CeedCopyMode,
454         );
455         let ierr = unsafe {
456             bind_ceed::CeedVectorSetArray(
457                 self.ptr,
458                 host,
459                 copy_mode,
460                 slice.as_ptr() as *mut crate::Scalar,
461             )
462         };
463         self.check_error(ierr)?;
464 
465         let mut ptr_copy = std::ptr::null_mut();
466         let ierr = unsafe { bind_ceed::CeedVectorReferenceCopy(self.ptr, &mut ptr_copy) };
467         self.check_error(ierr)?;
468 
469         Ok(crate::VectorSliceWrapper {
470             vector: crate::Vector::from_raw(ptr_copy)?,
471             _slice: slice,
472         })
473     }
474 
475     /// Sync the CeedVector to a specified memtype
476     ///
477     /// # arguments
478     ///
479     /// * `mtype` - Memtype to be synced
480     ///
481     /// ```
482     /// # use libceed::prelude::*;
483     /// # fn main() -> libceed::Result<()> {
484     /// # let ceed = libceed::Ceed::default_init();
485     /// let len = 10;
486     /// let mut vec = ceed.vector(len)?;
487     ///
488     /// let val = 42.0;
489     /// vec.set_value(val);
490     /// vec.sync(MemType::Host)?;
491     ///
492     /// vec.view()?.iter().for_each(|v| {
493     ///     assert_eq!(*v, val, "Value not set correctly");
494     /// });
495     /// # Ok(())
496     /// # }
497     /// ```
498     pub fn sync(&self, mtype: crate::MemType) -> crate::Result<i32> {
499         let ierr =
500             unsafe { bind_ceed::CeedVectorSyncArray(self.ptr, mtype as bind_ceed::CeedMemType) };
501         self.check_error(ierr)
502     }
503 
504     /// Create an immutable view
505     ///
506     /// ```
507     /// # use libceed::prelude::*;
508     /// # fn main() -> libceed::Result<()> {
509     /// # let ceed = libceed::Ceed::default_init();
510     /// let vec = ceed.vector_from_slice(&[10., 11., 12., 13.])?;
511     ///
512     /// let v = vec.view()?;
513     /// assert_eq!(v[0..2], [10., 11.]);
514     ///
515     /// // It is valid to have multiple immutable views
516     /// let w = vec.view()?;
517     /// assert_eq!(v[1..], w[1..]);
518     /// # Ok(())
519     /// # }
520     /// ```
521     pub fn view(&self) -> crate::Result<VectorView> {
522         VectorView::new(self)
523     }
524 
525     /// Create an mutable view
526     ///
527     /// ```
528     /// # use libceed::prelude::*;
529     /// # fn main() -> libceed::Result<()> {
530     /// # let ceed = libceed::Ceed::default_init();
531     /// let mut vec = ceed.vector_from_slice(&[10., 11., 12., 13.])?;
532     ///
533     /// {
534     ///     let mut v = vec.view_mut()?;
535     ///     v[2] = 9.;
536     /// }
537     ///
538     /// let w = vec.view()?;
539     /// assert_eq!(w[2], 9., "View did not mutate data");
540     /// # Ok(())
541     /// # }
542     /// ```
543     pub fn view_mut(&mut self) -> crate::Result<VectorViewMut> {
544         VectorViewMut::new(self)
545     }
546 
547     /// Return the norm of a CeedVector
548     ///
549     /// # arguments
550     ///
551     /// * `ntype` - Norm type One, Two, or Max
552     ///
553     /// ```
554     /// # use libceed::prelude::*;
555     /// # fn main() -> libceed::Result<()> {
556     /// # let ceed = libceed::Ceed::default_init();
557     /// let vec = ceed.vector_from_slice(&[1., 2., 3., 4.])?;
558     ///
559     /// let max_norm = vec.norm(NormType::Max)?;
560     /// assert_eq!(max_norm, 4.0, "Incorrect Max norm");
561     ///
562     /// let l1_norm = vec.norm(NormType::One)?;
563     /// assert_eq!(l1_norm, 10., "Incorrect L1 norm");
564     ///
565     /// let l2_norm = vec.norm(NormType::Two)?;
566     /// assert!((l2_norm - 5.477) < 1e-3, "Incorrect L2 norm");
567     /// # Ok(())
568     /// # }
569     /// ```
570     pub fn norm(&self, ntype: crate::NormType) -> crate::Result<crate::Scalar> {
571         let mut res: crate::Scalar = 0.0;
572         let ierr = unsafe {
573             bind_ceed::CeedVectorNorm(self.ptr, ntype as bind_ceed::CeedNormType, &mut res)
574         };
575         self.check_error(ierr)?;
576         Ok(res)
577     }
578 
579     /// Compute x = alpha x for a CeedVector
580     ///
581     /// # arguments
582     ///
583     /// * `alpha` - scaling factor
584     ///
585     /// ```
586     /// # use libceed::prelude::*;
587     /// # fn main() -> libceed::Result<()> {
588     /// # let ceed = libceed::Ceed::default_init();
589     /// let mut vec = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?;
590     ///
591     /// vec = vec.scale(-1.0)?;
592     /// vec.view()?.iter().enumerate().for_each(|(i, &v)| {
593     ///     assert_eq!(v, -(i as Scalar), "Value not set correctly");
594     /// });
595     /// # Ok(())
596     /// # }
597     /// ```
598     #[allow(unused_mut)]
599     pub fn scale(mut self, alpha: crate::Scalar) -> crate::Result<Self> {
600         let ierr = unsafe { bind_ceed::CeedVectorScale(self.ptr, alpha) };
601         self.check_error(ierr)?;
602         Ok(self)
603     }
604 
605     /// Compute y = alpha x + y for a pair of CeedVectors
606     ///
607     /// # arguments
608     ///
609     /// * `alpha` - scaling factor
610     /// * `x`     - second vector, must be different than self
611     ///
612     /// ```
613     /// # use libceed::prelude::*;
614     /// # fn main() -> libceed::Result<()> {
615     /// # let ceed = libceed::Ceed::default_init();
616     /// let x = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?;
617     /// let mut y = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?;
618     ///
619     /// y = y.axpy(-0.5, &x)?;
620     /// y.view()?.iter().enumerate().for_each(|(i, &v)| {
621     ///     assert_eq!(v, (i as Scalar) / 2.0, "Value not set correctly");
622     /// });
623     /// # Ok(())
624     /// # }
625     /// ```
626     #[allow(unused_mut)]
627     pub fn axpy(mut self, alpha: crate::Scalar, x: &crate::Vector) -> crate::Result<Self> {
628         let ierr = unsafe { bind_ceed::CeedVectorAXPY(self.ptr, alpha, x.ptr) };
629         self.check_error(ierr)?;
630         Ok(self)
631     }
632 
633     /// Compute the pointwise multiplication w = x .* y for CeedVectors
634     ///
635     /// # arguments
636     ///
637     /// * `x` - first vector for product
638     /// * `y` - second vector for product
639     ///
640     /// ```
641     /// # use libceed::prelude::*;
642     /// # fn main() -> libceed::Result<()> {
643     /// # let ceed = libceed::Ceed::default_init();
644     /// let mut w = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?;
645     /// let x = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?;
646     /// let y = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?;
647     ///
648     /// w = w.pointwise_mult(&x, &y)?;
649     /// w.view()?.iter().enumerate().for_each(|(i, &v)| {
650     ///     assert_eq!(v, (i as Scalar).powf(2.0), "Value not set correctly");
651     /// });
652     /// # Ok(())
653     /// # }
654     /// ```
655     #[allow(unused_mut)]
656     pub fn pointwise_mult(mut self, x: &crate::Vector, y: &crate::Vector) -> crate::Result<Self> {
657         let ierr = unsafe { bind_ceed::CeedVectorPointwiseMult(self.ptr, x.ptr, y.ptr) };
658         self.check_error(ierr)?;
659         Ok(self)
660     }
661 
662     /// Compute the pointwise multiplication w = w .* x for CeedVectors
663     ///
664     /// # arguments
665     ///
666     /// * `x` - second vector for product
667     ///
668     /// ```
669     /// # use libceed::prelude::*;
670     /// # fn main() -> libceed::Result<()> {
671     /// # let ceed = libceed::Ceed::default_init();
672     /// let mut w = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?;
673     /// let x = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?;
674     ///
675     /// w = w.pointwise_scale(&x)?;
676     /// w.view()?.iter().enumerate().for_each(|(i, &v)| {
677     ///     assert_eq!(v, (i as Scalar).powf(2.0), "Value not set correctly");
678     /// });
679     /// # Ok(())
680     /// # }
681     /// ```
682     #[allow(unused_mut)]
683     pub fn pointwise_scale(mut self, x: &crate::Vector) -> crate::Result<Self> {
684         let ierr = unsafe { bind_ceed::CeedVectorPointwiseMult(self.ptr, self.ptr, x.ptr) };
685         self.check_error(ierr)?;
686         Ok(self)
687     }
688 
689     /// Compute the pointwise multiplication w = w .* w for a CeedVector
690     ///
691     /// ```
692     /// # use libceed::prelude::*;
693     /// # fn main() -> libceed::Result<()> {
694     /// # let ceed = libceed::Ceed::default_init();
695     /// let mut w = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?;
696     ///
697     /// w = w.pointwise_square()?;
698     /// w.view()?.iter().enumerate().for_each(|(i, &v)| {
699     ///     assert_eq!(v, (i as Scalar).powf(2.0), "Value not set correctly");
700     /// });
701     /// # Ok(())
702     /// # }
703     /// ```
704     #[allow(unused_mut)]
705     pub fn pointwise_square(mut self) -> crate::Result<Self> {
706         let ierr = unsafe { bind_ceed::CeedVectorPointwiseMult(self.ptr, self.ptr, self.ptr) };
707         self.check_error(ierr)?;
708         Ok(self)
709     }
710 }
711 
712 // -----------------------------------------------------------------------------
713 // Vector Viewer
714 // -----------------------------------------------------------------------------
715 /// A (host) view of a Vector with Deref to slice.  We can't make
716 /// Vector itself Deref to slice because we can't handle the drop to
717 /// call bind_ceed::CeedVectorRestoreArrayRead().
718 #[derive(Debug)]
719 pub struct VectorView<'a> {
720     vec: &'a Vector<'a>,
721     array: *const crate::Scalar,
722 }
723 
724 impl<'a> VectorView<'a> {
725     /// Construct a VectorView from a Vector reference
726     fn new(vec: &'a Vector) -> crate::Result<Self> {
727         let mut array = std::ptr::null();
728         let ierr = unsafe {
729             bind_ceed::CeedVectorGetArrayRead(
730                 vec.ptr,
731                 crate::MemType::Host as bind_ceed::CeedMemType,
732                 &mut array,
733             )
734         };
735         vec.check_error(ierr)?;
736         Ok(Self {
737             vec: vec,
738             array: array,
739         })
740     }
741 }
742 
743 // Destructor
744 impl<'a> Drop for VectorView<'a> {
745     fn drop(&mut self) {
746         unsafe {
747             bind_ceed::CeedVectorRestoreArrayRead(self.vec.ptr, &mut self.array);
748         }
749     }
750 }
751 
752 // Data access
753 impl<'a> Deref for VectorView<'a> {
754     type Target = [crate::Scalar];
755     fn deref(&self) -> &[crate::Scalar] {
756         unsafe { std::slice::from_raw_parts(self.array, self.vec.len()) }
757     }
758 }
759 
760 // Viewing
761 impl<'a> fmt::Display for VectorView<'a> {
762     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
763         write!(f, "VectorView({:?})", self.deref())
764     }
765 }
766 
767 // -----------------------------------------------------------------------------
768 // Vector Viewer Mutable
769 // -----------------------------------------------------------------------------
770 /// A mutable (host) view of a Vector with Deref to slice.
771 #[derive(Debug)]
772 pub struct VectorViewMut<'a> {
773     vec: &'a Vector<'a>,
774     array: *mut crate::Scalar,
775 }
776 
777 impl<'a> VectorViewMut<'a> {
778     /// Construct a VectorViewMut from a Vector reference
779     fn new(vec: &'a mut Vector) -> crate::Result<Self> {
780         let mut ptr = std::ptr::null_mut();
781         let ierr = unsafe {
782             bind_ceed::CeedVectorGetArray(
783                 vec.ptr,
784                 crate::MemType::Host as bind_ceed::CeedMemType,
785                 &mut ptr,
786             )
787         };
788         vec.check_error(ierr)?;
789         Ok(Self {
790             vec: vec,
791             array: ptr,
792         })
793     }
794 }
795 
796 // Destructor
797 impl<'a> Drop for VectorViewMut<'a> {
798     fn drop(&mut self) {
799         unsafe {
800             bind_ceed::CeedVectorRestoreArray(self.vec.ptr, &mut self.array);
801         }
802     }
803 }
804 
805 // Data access
806 impl<'a> Deref for VectorViewMut<'a> {
807     type Target = [crate::Scalar];
808     fn deref(&self) -> &[crate::Scalar] {
809         unsafe { std::slice::from_raw_parts(self.array, self.vec.len()) }
810     }
811 }
812 
813 // Mutable data access
814 impl<'a> DerefMut for VectorViewMut<'a> {
815     fn deref_mut(&mut self) -> &mut [crate::Scalar] {
816         unsafe { std::slice::from_raw_parts_mut(self.array, self.vec.len()) }
817     }
818 }
819 
820 // Viewing
821 impl<'a> fmt::Display for VectorViewMut<'a> {
822     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
823         write!(f, "VectorViewMut({:?})", self.deref())
824     }
825 }
826 
827 // -----------------------------------------------------------------------------
828