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 // Vector 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 // Vector 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 // Convenience constructor 158 // ----------------------------------------------------------------------------- 159 impl<'a> VectorSliceWrapper<'a> { 160 fn from_vector_and_slice_mut<'b>( 161 vec: &'b mut crate::Vector, 162 slice: &'a mut [crate::Scalar], 163 ) -> crate::Result<Self> { 164 assert_eq!(vec.length(), slice.len()); 165 let (host, copy_mode) = ( 166 crate::MemType::Host as bind_ceed::CeedMemType, 167 crate::CopyMode::UsePointer as bind_ceed::CeedCopyMode, 168 ); 169 let ierr = unsafe { 170 bind_ceed::CeedVectorSetArray( 171 vec.ptr, 172 host, 173 copy_mode, 174 slice.as_ptr() as *mut crate::Scalar, 175 ) 176 }; 177 vec.check_error(ierr)?; 178 179 Ok(Self { 180 vector: crate::Vector::from_raw(vec.ptr_copy_mut()?)?, 181 _slice: slice, 182 }) 183 } 184 } 185 186 // ----------------------------------------------------------------------------- 187 // Vector context wrapper 188 // ----------------------------------------------------------------------------- 189 #[derive(Debug)] 190 pub struct Vector<'a> { 191 pub(crate) ptr: bind_ceed::CeedVector, 192 _lifeline: PhantomData<&'a ()>, 193 } 194 impl From<&'_ Vector<'_>> for bind_ceed::CeedVector { 195 fn from(vec: &Vector) -> Self { 196 vec.ptr 197 } 198 } 199 200 // ----------------------------------------------------------------------------- 201 // Destructor 202 // ----------------------------------------------------------------------------- 203 impl<'a> Drop for Vector<'a> { 204 fn drop(&mut self) { 205 let not_none_and_active = self.ptr != unsafe { bind_ceed::CEED_VECTOR_NONE } 206 && self.ptr != unsafe { bind_ceed::CEED_VECTOR_ACTIVE }; 207 208 if not_none_and_active { 209 unsafe { bind_ceed::CeedVectorDestroy(&mut self.ptr) }; 210 } 211 } 212 } 213 214 // ----------------------------------------------------------------------------- 215 // Display 216 // ----------------------------------------------------------------------------- 217 impl<'a> fmt::Display for Vector<'a> { 218 /// View a Vector 219 /// 220 /// ``` 221 /// # use libceed::prelude::*; 222 /// # fn main() -> libceed::Result<()> { 223 /// # let ceed = libceed::Ceed::default_init(); 224 /// let vec = libceed::vector::Vector::from_slice(&ceed, &[1., 2., 3.])?; 225 /// assert_eq!( 226 /// vec.to_string(), 227 /// "CeedVector length 3 228 /// 1.00000000 229 /// 2.00000000 230 /// 3.00000000 231 /// " 232 /// ); 233 /// # Ok(()) 234 /// # } 235 /// ``` 236 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 237 let mut ptr = std::ptr::null_mut(); 238 let mut sizeloc = crate::MAX_BUFFER_LENGTH; 239 let format = CString::new("%12.8f").expect("CString::new failed"); 240 let format_c: *const c_char = format.into_raw(); 241 let cstring = unsafe { 242 let file = bind_ceed::open_memstream(&mut ptr, &mut sizeloc); 243 bind_ceed::CeedVectorView(self.ptr, format_c, file); 244 bind_ceed::fclose(file); 245 CString::from_raw(ptr) 246 }; 247 cstring.to_string_lossy().fmt(f) 248 } 249 } 250 251 // ----------------------------------------------------------------------------- 252 // Implementations 253 // ----------------------------------------------------------------------------- 254 impl<'a> Vector<'a> { 255 // Constructors 256 pub fn create(ceed: &crate::Ceed, n: usize) -> crate::Result<Self> { 257 let n = isize::try_from(n).unwrap(); 258 let mut ptr = std::ptr::null_mut(); 259 let ierr = unsafe { bind_ceed::CeedVectorCreate(ceed.ptr, n, &mut ptr) }; 260 ceed.check_error(ierr)?; 261 Ok(Self { 262 ptr, 263 _lifeline: PhantomData, 264 }) 265 } 266 267 pub(crate) fn from_raw(ptr: bind_ceed::CeedVector) -> crate::Result<Self> { 268 Ok(Self { 269 ptr, 270 _lifeline: PhantomData, 271 }) 272 } 273 274 fn ptr_copy_mut(&mut self) -> crate::Result<bind_ceed::CeedVector> { 275 let mut ptr_copy = std::ptr::null_mut(); 276 let ierr = unsafe { bind_ceed::CeedVectorReferenceCopy(self.ptr, &mut ptr_copy) }; 277 self.check_error(ierr)?; 278 Ok(ptr_copy) 279 } 280 281 /// Create a Vector from a slice 282 /// 283 /// # arguments 284 /// 285 /// * `slice` - values to initialize vector with 286 /// 287 /// ``` 288 /// # use libceed::prelude::*; 289 /// # fn main() -> libceed::Result<()> { 290 /// # let ceed = libceed::Ceed::default_init(); 291 /// let vec = vector::Vector::from_slice(&ceed, &[1., 2., 3.])?; 292 /// assert_eq!(vec.length(), 3, "Incorrect length from slice"); 293 /// # Ok(()) 294 /// # } 295 /// ``` 296 pub fn from_slice(ceed: &crate::Ceed, v: &[crate::Scalar]) -> crate::Result<Self> { 297 let mut x = Self::create(ceed, v.len())?; 298 x.set_slice(v)?; 299 Ok(x) 300 } 301 302 /// Create a Vector from a mutable array reference 303 /// 304 /// # arguments 305 /// 306 /// * `slice` - values to initialize vector with 307 /// 308 /// ``` 309 /// # use libceed::prelude::*; 310 /// # fn main() -> libceed::Result<()> { 311 /// # let ceed = libceed::Ceed::default_init(); 312 /// let mut rust_vec = vec![1., 2., 3.]; 313 /// let vec = libceed::vector::Vector::from_array(&ceed, &mut rust_vec)?; 314 /// 315 /// assert_eq!(vec.length(), 3, "Incorrect length from slice"); 316 /// # Ok(()) 317 /// # } 318 /// ``` 319 pub fn from_array(ceed: &crate::Ceed, v: &mut [crate::Scalar]) -> crate::Result<Self> { 320 let x = Self::create(ceed, v.len())?; 321 let (host, user_pointer) = ( 322 crate::MemType::Host as bind_ceed::CeedMemType, 323 crate::CopyMode::UsePointer as bind_ceed::CeedCopyMode, 324 ); 325 let v = v.as_ptr() as *mut crate::Scalar; 326 let ierr = unsafe { bind_ceed::CeedVectorSetArray(x.ptr, host, user_pointer, v) }; 327 ceed.check_error(ierr)?; 328 Ok(x) 329 } 330 331 // Error handling 332 #[doc(hidden)] 333 fn check_error(&self, ierr: i32) -> crate::Result<i32> { 334 let mut ptr = std::ptr::null_mut(); 335 unsafe { 336 bind_ceed::CeedVectorGetCeed(self.ptr, &mut ptr); 337 } 338 crate::check_error(ptr, ierr) 339 } 340 341 /// Returns the length of a Vector 342 /// 343 /// ``` 344 /// # use libceed::prelude::*; 345 /// # fn main() -> libceed::Result<()> { 346 /// # let ceed = libceed::Ceed::default_init(); 347 /// let vec = ceed.vector(10)?; 348 /// 349 /// let n = vec.length(); 350 /// assert_eq!(n, 10, "Incorrect length"); 351 /// # Ok(()) 352 /// # } 353 /// ``` 354 pub fn length(&self) -> usize { 355 let mut n = 0; 356 unsafe { bind_ceed::CeedVectorGetLength(self.ptr, &mut n) }; 357 usize::try_from(n).unwrap() 358 } 359 360 /// Returns the length of a Vector 361 /// 362 /// ``` 363 /// # use libceed::prelude::*; 364 /// # fn main() -> libceed::Result<()> { 365 /// # let ceed = libceed::Ceed::default_init(); 366 /// let vec = ceed.vector(10)?; 367 /// assert_eq!(vec.len(), 10, "Incorrect length"); 368 /// # Ok(()) 369 /// # } 370 /// ``` 371 pub fn len(&self) -> usize { 372 self.length() 373 } 374 375 /// Set the Vector to a constant value 376 /// 377 /// # arguments 378 /// 379 /// * `val` - Value to be used 380 /// 381 /// ``` 382 /// # use libceed::prelude::*; 383 /// # fn main() -> libceed::Result<()> { 384 /// # let ceed = libceed::Ceed::default_init(); 385 /// let len = 10; 386 /// let mut vec = ceed.vector(len)?; 387 /// 388 /// let val = 42.0; 389 /// vec.set_value(val)?; 390 /// 391 /// for v in vec.view()?.iter() { 392 /// assert_eq!(*v, val, "Value not set correctly"); 393 /// } 394 /// # Ok(()) 395 /// # } 396 /// ``` 397 pub fn set_value(&mut self, value: crate::Scalar) -> crate::Result<i32> { 398 let ierr = unsafe { bind_ceed::CeedVectorSetValue(self.ptr, value) }; 399 self.check_error(ierr) 400 } 401 402 /// Set values from a slice of the same length 403 /// 404 /// # arguments 405 /// 406 /// * `slice` - values to into self; length must match 407 /// 408 /// ``` 409 /// # use libceed::prelude::*; 410 /// # fn main() -> libceed::Result<()> { 411 /// # let ceed = libceed::Ceed::default_init(); 412 /// let mut vec = ceed.vector(4)?; 413 /// vec.set_slice(&[10., 11., 12., 13.])?; 414 /// 415 /// for (i, v) in vec.view()?.iter().enumerate() { 416 /// assert_eq!(*v, 10. + i as Scalar, "Slice not set correctly"); 417 /// } 418 /// # Ok(()) 419 /// # } 420 /// ``` 421 pub fn set_slice(&mut self, slice: &[crate::Scalar]) -> crate::Result<i32> { 422 assert_eq!(self.length(), slice.len()); 423 let (host, copy_mode) = ( 424 crate::MemType::Host as bind_ceed::CeedMemType, 425 crate::CopyMode::CopyValues as bind_ceed::CeedCopyMode, 426 ); 427 let ierr = unsafe { 428 bind_ceed::CeedVectorSetArray( 429 self.ptr, 430 host, 431 copy_mode, 432 slice.as_ptr() as *mut crate::Scalar, 433 ) 434 }; 435 self.check_error(ierr) 436 } 437 438 /// Wrap a mutable slice in a Vector of the same length 439 /// 440 /// # arguments 441 /// 442 /// * `slice` - values to wrap in self; length must match 443 /// 444 /// ``` 445 /// # use libceed::prelude::*; 446 /// # fn main() -> libceed::Result<()> { 447 /// # let ceed = libceed::Ceed::default_init(); 448 /// let mut vec = ceed.vector(4)?; 449 /// let mut array = [10., 11., 12., 13.]; 450 /// 451 /// { 452 /// // `wrapper` holds a mutable reference to the wrapped slice 453 /// // that is dropped when `wrapper` goes out of scope 454 /// let wrapper = vec.wrap_slice_mut(&mut array)?; 455 /// for (i, v) in vec.view()?.iter().enumerate() { 456 /// assert_eq!(*v, 10. + i as Scalar, "Slice not set correctly"); 457 /// } 458 /// 459 /// // This line will not compile, as the `wrapper` holds mutable 460 /// // access to the `array` 461 /// // array[0] = 5.0; 462 /// 463 /// // Changes here are reflected in the `array` 464 /// vec.set_value(5.0)?; 465 /// for v in vec.view()?.iter() { 466 /// assert_eq!(*v, 5.0 as Scalar, "Value not set correctly"); 467 /// } 468 /// } 469 /// 470 /// // 'array' remains changed 471 /// for v in array.iter() { 472 /// assert_eq!(*v, 5.0 as Scalar, "Array not mutated correctly"); 473 /// } 474 /// 475 /// // While changes to `vec` no longer affect `array` 476 /// vec.set_value(6.0)?; 477 /// for v in array.iter() { 478 /// assert_eq!(*v, 5.0 as Scalar, "Array mutated without permission"); 479 /// } 480 /// # Ok(()) 481 /// # } 482 /// ``` 483 pub fn wrap_slice_mut<'b>( 484 &mut self, 485 slice: &'b mut [crate::Scalar], 486 ) -> crate::Result<VectorSliceWrapper<'b>> { 487 crate::VectorSliceWrapper::from_vector_and_slice_mut(self, slice) 488 } 489 490 /// Sync the Vector to a specified memtype 491 /// 492 /// # arguments 493 /// 494 /// * `mtype` - Memtype to be synced 495 /// 496 /// ``` 497 /// # use libceed::prelude::*; 498 /// # fn main() -> libceed::Result<()> { 499 /// # let ceed = libceed::Ceed::default_init(); 500 /// let len = 10; 501 /// let mut vec = ceed.vector(len)?; 502 /// 503 /// let val = 42.0; 504 /// vec.set_value(val); 505 /// vec.sync(MemType::Host)?; 506 /// 507 /// for v in vec.view()?.iter() { 508 /// assert_eq!(*v, val, "Value not set correctly"); 509 /// } 510 /// # Ok(()) 511 /// # } 512 /// ``` 513 pub fn sync(&self, mtype: crate::MemType) -> crate::Result<i32> { 514 let ierr = 515 unsafe { bind_ceed::CeedVectorSyncArray(self.ptr, mtype as bind_ceed::CeedMemType) }; 516 self.check_error(ierr) 517 } 518 519 /// Create an immutable view 520 /// 521 /// ``` 522 /// # use libceed::prelude::*; 523 /// # fn main() -> libceed::Result<()> { 524 /// # let ceed = libceed::Ceed::default_init(); 525 /// let vec = ceed.vector_from_slice(&[10., 11., 12., 13.])?; 526 /// 527 /// let v = vec.view()?; 528 /// assert_eq!(v[0..2], [10., 11.]); 529 /// 530 /// // It is valid to have multiple immutable views 531 /// let w = vec.view()?; 532 /// assert_eq!(v[1..], w[1..]); 533 /// # Ok(()) 534 /// # } 535 /// ``` 536 pub fn view(&self) -> crate::Result<VectorView> { 537 VectorView::new(self) 538 } 539 540 /// Create an mutable view 541 /// 542 /// ``` 543 /// # use libceed::prelude::*; 544 /// # fn main() -> libceed::Result<()> { 545 /// # let ceed = libceed::Ceed::default_init(); 546 /// let mut vec = ceed.vector_from_slice(&[10., 11., 12., 13.])?; 547 /// 548 /// { 549 /// let mut v = vec.view_mut()?; 550 /// v[2] = 9.; 551 /// } 552 /// 553 /// let w = vec.view()?; 554 /// assert_eq!(w[2], 9., "View did not mutate data"); 555 /// # Ok(()) 556 /// # } 557 /// ``` 558 pub fn view_mut(&mut self) -> crate::Result<VectorViewMut> { 559 VectorViewMut::new(self) 560 } 561 562 /// Return the norm of a Vector 563 /// 564 /// # arguments 565 /// 566 /// * `ntype` - Norm type One, Two, or Max 567 /// 568 /// ``` 569 /// # use libceed::prelude::*; 570 /// # fn main() -> libceed::Result<()> { 571 /// # let ceed = libceed::Ceed::default_init(); 572 /// let vec = ceed.vector_from_slice(&[1., 2., 3., 4.])?; 573 /// 574 /// let max_norm = vec.norm(NormType::Max)?; 575 /// assert_eq!(max_norm, 4.0, "Incorrect Max norm"); 576 /// 577 /// let l1_norm = vec.norm(NormType::One)?; 578 /// assert_eq!(l1_norm, 10., "Incorrect L1 norm"); 579 /// 580 /// let l2_norm = vec.norm(NormType::Two)?; 581 /// assert!((l2_norm - 5.477) < 1e-3, "Incorrect L2 norm"); 582 /// # Ok(()) 583 /// # } 584 /// ``` 585 pub fn norm(&self, ntype: crate::NormType) -> crate::Result<crate::Scalar> { 586 let mut res: crate::Scalar = 0.0; 587 let ierr = unsafe { 588 bind_ceed::CeedVectorNorm(self.ptr, ntype as bind_ceed::CeedNormType, &mut res) 589 }; 590 self.check_error(ierr)?; 591 Ok(res) 592 } 593 594 /// Compute x = alpha x for a Vector 595 /// 596 /// # arguments 597 /// 598 /// * `alpha` - scaling factor 599 /// 600 /// ``` 601 /// # use libceed::prelude::*; 602 /// # fn main() -> libceed::Result<()> { 603 /// # let ceed = libceed::Ceed::default_init(); 604 /// let mut vec = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?; 605 /// 606 /// vec = vec.scale(-1.0)?; 607 /// for (i, v) in vec.view()?.iter().enumerate() { 608 /// assert_eq!(*v, -(i as Scalar), "Value not set correctly"); 609 /// } 610 /// # Ok(()) 611 /// # } 612 /// ``` 613 #[allow(unused_mut)] 614 pub fn scale(mut self, alpha: crate::Scalar) -> crate::Result<Self> { 615 let ierr = unsafe { bind_ceed::CeedVectorScale(self.ptr, alpha) }; 616 self.check_error(ierr)?; 617 Ok(self) 618 } 619 620 /// Compute y = alpha x + y for a pair of Vectors 621 /// 622 /// # arguments 623 /// 624 /// * `alpha` - scaling factor 625 /// * `x` - second vector, must be different than self 626 /// 627 /// ``` 628 /// # use libceed::prelude::*; 629 /// # fn main() -> libceed::Result<()> { 630 /// # let ceed = libceed::Ceed::default_init(); 631 /// let x = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?; 632 /// let mut y = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?; 633 /// 634 /// y = y.axpy(-0.5, &x)?; 635 /// for (i, y) in y.view()?.iter().enumerate() { 636 /// assert_eq!(*y, (i as Scalar) / 2.0, "Value not set correctly"); 637 /// } 638 /// # Ok(()) 639 /// # } 640 /// ``` 641 #[allow(unused_mut)] 642 pub fn axpy(mut self, alpha: crate::Scalar, x: &crate::Vector) -> crate::Result<Self> { 643 let ierr = unsafe { bind_ceed::CeedVectorAXPY(self.ptr, alpha, x.ptr) }; 644 self.check_error(ierr)?; 645 Ok(self) 646 } 647 648 /// Compute the pointwise multiplication w = x .* y for Vectors 649 /// 650 /// # arguments 651 /// 652 /// * `x` - first vector for product 653 /// * `y` - second vector for product 654 /// 655 /// ``` 656 /// # use libceed::prelude::*; 657 /// # fn main() -> libceed::Result<()> { 658 /// # let ceed = libceed::Ceed::default_init(); 659 /// let mut w = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?; 660 /// let x = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?; 661 /// let y = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?; 662 /// 663 /// w = w.pointwise_mult(&x, &y)?; 664 /// for (i, w) in w.view()?.iter().enumerate() { 665 /// assert_eq!(*w, (i as Scalar).powf(2.0), "Value not set correctly"); 666 /// } 667 /// # Ok(()) 668 /// # } 669 /// ``` 670 #[allow(unused_mut)] 671 pub fn pointwise_mult(mut self, x: &crate::Vector, y: &crate::Vector) -> crate::Result<Self> { 672 let ierr = unsafe { bind_ceed::CeedVectorPointwiseMult(self.ptr, x.ptr, y.ptr) }; 673 self.check_error(ierr)?; 674 Ok(self) 675 } 676 677 /// Compute the pointwise multiplication w = w .* x for Vectors 678 /// 679 /// # arguments 680 /// 681 /// * `x` - second vector for product 682 /// 683 /// ``` 684 /// # use libceed::prelude::*; 685 /// # fn main() -> libceed::Result<()> { 686 /// # let ceed = libceed::Ceed::default_init(); 687 /// let mut w = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?; 688 /// let x = ceed.vector_from_slice(&[0., 1., 2., 3., 4.])?; 689 /// 690 /// w = w.pointwise_scale(&x)?; 691 /// for (i, w) in w.view()?.iter().enumerate() { 692 /// assert_eq!(*w, (i as Scalar).powf(2.0), "Value not set correctly"); 693 /// } 694 /// # Ok(()) 695 /// # } 696 /// ``` 697 #[allow(unused_mut)] 698 pub fn pointwise_scale(mut self, x: &crate::Vector) -> crate::Result<Self> { 699 let ierr = unsafe { bind_ceed::CeedVectorPointwiseMult(self.ptr, self.ptr, x.ptr) }; 700 self.check_error(ierr)?; 701 Ok(self) 702 } 703 704 /// Compute the pointwise multiplication w = w .* w for a Vector 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 /// 712 /// w = w.pointwise_square()?; 713 /// for (i, w) in w.view()?.iter().enumerate() { 714 /// assert_eq!(*w, (i as Scalar).powf(2.0), "Value not set correctly"); 715 /// } 716 /// # Ok(()) 717 /// # } 718 /// ``` 719 #[allow(unused_mut)] 720 pub fn pointwise_square(mut self) -> crate::Result<Self> { 721 let ierr = unsafe { bind_ceed::CeedVectorPointwiseMult(self.ptr, self.ptr, self.ptr) }; 722 self.check_error(ierr)?; 723 Ok(self) 724 } 725 } 726 727 // ----------------------------------------------------------------------------- 728 // Vector Viewer 729 // ----------------------------------------------------------------------------- 730 /// A (host) view of a Vector with Deref to slice. We can't make 731 /// Vector itself Deref to slice because we can't handle the drop to 732 /// call bind_ceed::CeedVectorRestoreArrayRead(). 733 #[derive(Debug)] 734 pub struct VectorView<'a> { 735 vec: &'a Vector<'a>, 736 array: *const crate::Scalar, 737 } 738 739 impl<'a> VectorView<'a> { 740 /// Construct a VectorView from a Vector reference 741 fn new(vec: &'a Vector) -> crate::Result<Self> { 742 let mut array = std::ptr::null(); 743 let ierr = unsafe { 744 bind_ceed::CeedVectorGetArrayRead( 745 vec.ptr, 746 crate::MemType::Host as bind_ceed::CeedMemType, 747 &mut array, 748 ) 749 }; 750 vec.check_error(ierr)?; 751 Ok(Self { 752 vec: vec, 753 array: array, 754 }) 755 } 756 } 757 758 // Destructor 759 impl<'a> Drop for VectorView<'a> { 760 fn drop(&mut self) { 761 unsafe { 762 bind_ceed::CeedVectorRestoreArrayRead(self.vec.ptr, &mut self.array); 763 } 764 } 765 } 766 767 // Data access 768 impl<'a> Deref for VectorView<'a> { 769 type Target = [crate::Scalar]; 770 fn deref(&self) -> &[crate::Scalar] { 771 unsafe { std::slice::from_raw_parts(self.array, self.vec.len()) } 772 } 773 } 774 775 // Viewing 776 impl<'a> fmt::Display for VectorView<'a> { 777 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 778 write!(f, "VectorView({:?})", self.deref()) 779 } 780 } 781 782 // ----------------------------------------------------------------------------- 783 // Vector Viewer Mutable 784 // ----------------------------------------------------------------------------- 785 /// A mutable (host) view of a Vector with Deref to slice. 786 #[derive(Debug)] 787 pub struct VectorViewMut<'a> { 788 vec: &'a Vector<'a>, 789 array: *mut crate::Scalar, 790 } 791 792 impl<'a> VectorViewMut<'a> { 793 /// Construct a VectorViewMut from a Vector reference 794 fn new(vec: &'a mut Vector) -> crate::Result<Self> { 795 let mut ptr = std::ptr::null_mut(); 796 let ierr = unsafe { 797 bind_ceed::CeedVectorGetArray( 798 vec.ptr, 799 crate::MemType::Host as bind_ceed::CeedMemType, 800 &mut ptr, 801 ) 802 }; 803 vec.check_error(ierr)?; 804 Ok(Self { 805 vec: vec, 806 array: ptr, 807 }) 808 } 809 } 810 811 // Destructor 812 impl<'a> Drop for VectorViewMut<'a> { 813 fn drop(&mut self) { 814 unsafe { 815 bind_ceed::CeedVectorRestoreArray(self.vec.ptr, &mut self.array); 816 } 817 } 818 } 819 820 // Data access 821 impl<'a> Deref for VectorViewMut<'a> { 822 type Target = [crate::Scalar]; 823 fn deref(&self) -> &[crate::Scalar] { 824 unsafe { std::slice::from_raw_parts(self.array, self.vec.len()) } 825 } 826 } 827 828 // Mutable data access 829 impl<'a> DerefMut for VectorViewMut<'a> { 830 fn deref_mut(&mut self) -> &mut [crate::Scalar] { 831 unsafe { std::slice::from_raw_parts_mut(self.array, self.vec.len()) } 832 } 833 } 834 835 // Viewing 836 impl<'a> fmt::Display for VectorViewMut<'a> { 837 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 838 write!(f, "VectorViewMut({:?})", self.deref()) 839 } 840 } 841 842 // ----------------------------------------------------------------------------- 843