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