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