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