19df49d7eSJed Brown // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 29df49d7eSJed Brown // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 39df49d7eSJed Brown // reserved. See files LICENSE and NOTICE for details. 49df49d7eSJed Brown // 59df49d7eSJed Brown // This file is part of CEED, a collection of benchmarks, miniapps, software 69df49d7eSJed Brown // libraries and APIs for efficient high-order finite element and spectral 79df49d7eSJed Brown // element discretizations for exascale applications. For more information and 89df49d7eSJed Brown // source code availability see http://github.com/ceed. 99df49d7eSJed Brown // 109df49d7eSJed Brown // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 119df49d7eSJed Brown // a collaborative effort of two U.S. Department of Energy organizations (Office 129df49d7eSJed Brown // of Science and the National Nuclear Security Administration) responsible for 139df49d7eSJed Brown // the planning and preparation of a capable exascale ecosystem, including 149df49d7eSJed Brown // software, applications, hardware, advanced system engineering and early 159df49d7eSJed Brown // testbed platforms, in support of the nation's exascale computing imperative 169df49d7eSJed Brown 179df49d7eSJed Brown //! A Ceed Operator defines the finite/spectral element operator associated to a 189df49d7eSJed Brown //! Ceed QFunction. A Ceed Operator connects Ceed ElemRestrictions, 199df49d7eSJed Brown //! Ceed Bases, and Ceed QFunctions. 209df49d7eSJed Brown 219df49d7eSJed Brown use crate::prelude::*; 229df49d7eSJed Brown 239df49d7eSJed Brown // ----------------------------------------------------------------------------- 2408778c6fSJeremy L Thompson // CeedOperator Field context wrapper 2508778c6fSJeremy L Thompson // ----------------------------------------------------------------------------- 2608778c6fSJeremy L Thompson #[derive(Debug)] 2708778c6fSJeremy L Thompson pub struct OperatorField<'a> { 2808778c6fSJeremy L Thompson pub(crate) ptr: bind_ceed::CeedOperatorField, 2908778c6fSJeremy L Thompson _lifeline: PhantomData<&'a ()>, 3008778c6fSJeremy L Thompson } 3108778c6fSJeremy L Thompson 3208778c6fSJeremy L Thompson // ----------------------------------------------------------------------------- 3308778c6fSJeremy L Thompson // Implementations 3408778c6fSJeremy L Thompson // ----------------------------------------------------------------------------- 3508778c6fSJeremy L Thompson impl<'a> OperatorField<'a> { 3608778c6fSJeremy L Thompson /// Get the name of an OperatorField 3708778c6fSJeremy L Thompson /// 3808778c6fSJeremy L Thompson /// ``` 3908778c6fSJeremy L Thompson /// # use libceed::prelude::*; 404d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 4108778c6fSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 4208778c6fSJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 4308778c6fSJeremy L Thompson /// 4408778c6fSJeremy L Thompson /// // Operator field arguments 4508778c6fSJeremy L Thompson /// let ne = 3; 4608778c6fSJeremy L Thompson /// let q = 4 as usize; 4708778c6fSJeremy L Thompson /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 4808778c6fSJeremy L Thompson /// for i in 0..ne { 4908778c6fSJeremy L Thompson /// ind[2 * i + 0] = i as i32; 5008778c6fSJeremy L Thompson /// ind[2 * i + 1] = (i + 1) as i32; 5108778c6fSJeremy L Thompson /// } 5208778c6fSJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 5308778c6fSJeremy L Thompson /// let strides: [i32; 3] = [1, q as i32, q as i32]; 5408778c6fSJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, 2, 1, q * ne, strides)?; 5508778c6fSJeremy L Thompson /// 5608778c6fSJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 5708778c6fSJeremy L Thompson /// 5808778c6fSJeremy L Thompson /// // Operator fields 5908778c6fSJeremy L Thompson /// let op = ceed 6008778c6fSJeremy L Thompson /// .operator(&qf, QFunctionOpt::None, QFunctionOpt::None)? 6108778c6fSJeremy L Thompson /// .field("dx", &r, &b, VectorOpt::Active)? 6208778c6fSJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &b, VectorOpt::None)? 6308778c6fSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)?; 6408778c6fSJeremy L Thompson /// 6508778c6fSJeremy L Thompson /// let inputs = op.inputs()?; 6608778c6fSJeremy L Thompson /// 6708778c6fSJeremy L Thompson /// assert_eq!(inputs[0].name(), "dx", "Incorrect input name"); 6808778c6fSJeremy L Thompson /// assert_eq!(inputs[1].name(), "weights", "Incorrect input name"); 6908778c6fSJeremy L Thompson /// # Ok(()) 7008778c6fSJeremy L Thompson /// # } 7108778c6fSJeremy L Thompson /// ``` 7208778c6fSJeremy L Thompson pub fn name(&self) -> &str { 7308778c6fSJeremy L Thompson let mut name_ptr: *mut std::os::raw::c_char = std::ptr::null_mut(); 7408778c6fSJeremy L Thompson unsafe { 7508778c6fSJeremy L Thompson bind_ceed::CeedOperatorFieldGetName(self.ptr, &mut name_ptr); 7608778c6fSJeremy L Thompson } 7708778c6fSJeremy L Thompson unsafe { CStr::from_ptr(name_ptr) }.to_str().unwrap() 7808778c6fSJeremy L Thompson } 7908778c6fSJeremy L Thompson 8008778c6fSJeremy L Thompson /// Get the ElemRestriction of an OperatorField 8108778c6fSJeremy L Thompson /// 8208778c6fSJeremy L Thompson /// ``` 8308778c6fSJeremy L Thompson /// # use libceed::prelude::*; 844d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 8508778c6fSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 8608778c6fSJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 8708778c6fSJeremy L Thompson /// 8808778c6fSJeremy L Thompson /// // Operator field arguments 8908778c6fSJeremy L Thompson /// let ne = 3; 9008778c6fSJeremy L Thompson /// let q = 4 as usize; 9108778c6fSJeremy L Thompson /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 9208778c6fSJeremy L Thompson /// for i in 0..ne { 9308778c6fSJeremy L Thompson /// ind[2 * i + 0] = i as i32; 9408778c6fSJeremy L Thompson /// ind[2 * i + 1] = (i + 1) as i32; 9508778c6fSJeremy L Thompson /// } 9608778c6fSJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 9708778c6fSJeremy L Thompson /// let strides: [i32; 3] = [1, q as i32, q as i32]; 9808778c6fSJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, 2, 1, q * ne, strides)?; 9908778c6fSJeremy L Thompson /// 10008778c6fSJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 10108778c6fSJeremy L Thompson /// 10208778c6fSJeremy L Thompson /// // Operator fields 10308778c6fSJeremy L Thompson /// let op = ceed 10408778c6fSJeremy L Thompson /// .operator(&qf, QFunctionOpt::None, QFunctionOpt::None)? 10508778c6fSJeremy L Thompson /// .field("dx", &r, &b, VectorOpt::Active)? 10608778c6fSJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &b, VectorOpt::None)? 10708778c6fSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)?; 10808778c6fSJeremy L Thompson /// 10908778c6fSJeremy L Thompson /// let inputs = op.inputs()?; 11008778c6fSJeremy L Thompson /// 11108778c6fSJeremy L Thompson /// assert!( 11208778c6fSJeremy L Thompson /// inputs[0].elem_restriction().is_some(), 11308778c6fSJeremy L Thompson /// "Incorrect field ElemRestriction" 11408778c6fSJeremy L Thompson /// ); 11508778c6fSJeremy L Thompson /// if let ElemRestrictionOpt::Some(r) = inputs[0].elem_restriction() { 11608778c6fSJeremy L Thompson /// assert_eq!( 11708778c6fSJeremy L Thompson /// r.num_elements(), 11808778c6fSJeremy L Thompson /// ne, 11908778c6fSJeremy L Thompson /// "Incorrect field ElemRestriction number of elements" 12008778c6fSJeremy L Thompson /// ); 12108778c6fSJeremy L Thompson /// } 12208778c6fSJeremy L Thompson /// 12308778c6fSJeremy L Thompson /// assert!( 12408778c6fSJeremy L Thompson /// inputs[1].elem_restriction().is_none(), 12508778c6fSJeremy L Thompson /// "Incorrect field ElemRestriction" 12608778c6fSJeremy L Thompson /// ); 12708778c6fSJeremy L Thompson /// # Ok(()) 12808778c6fSJeremy L Thompson /// # } 12908778c6fSJeremy L Thompson /// ``` 13008778c6fSJeremy L Thompson pub fn elem_restriction(&self) -> ElemRestrictionOpt { 13108778c6fSJeremy L Thompson let mut ptr = std::ptr::null_mut(); 13208778c6fSJeremy L Thompson unsafe { 13308778c6fSJeremy L Thompson bind_ceed::CeedOperatorFieldGetElemRestriction(self.ptr, &mut ptr); 13408778c6fSJeremy L Thompson } 13508778c6fSJeremy L Thompson if ptr == unsafe { bind_ceed::CEED_ELEMRESTRICTION_NONE } { 13608778c6fSJeremy L Thompson ElemRestrictionOpt::None 13708778c6fSJeremy L Thompson } else { 13808778c6fSJeremy L Thompson let slice = unsafe { 13908778c6fSJeremy L Thompson std::slice::from_raw_parts( 14008778c6fSJeremy L Thompson &ptr as *const bind_ceed::CeedElemRestriction as *const crate::ElemRestriction, 14108778c6fSJeremy L Thompson 1 as usize, 14208778c6fSJeremy L Thompson ) 14308778c6fSJeremy L Thompson }; 14408778c6fSJeremy L Thompson ElemRestrictionOpt::Some(&slice[0]) 14508778c6fSJeremy L Thompson } 14608778c6fSJeremy L Thompson } 14708778c6fSJeremy L Thompson 14808778c6fSJeremy L Thompson /// Get the Basis of an OperatorField 14908778c6fSJeremy L Thompson /// 15008778c6fSJeremy L Thompson /// ``` 15108778c6fSJeremy L Thompson /// # use libceed::prelude::*; 1524d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 15308778c6fSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 15408778c6fSJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 15508778c6fSJeremy L Thompson /// 15608778c6fSJeremy L Thompson /// // Operator field arguments 15708778c6fSJeremy L Thompson /// let ne = 3; 15808778c6fSJeremy L Thompson /// let q = 4 as usize; 15908778c6fSJeremy L Thompson /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 16008778c6fSJeremy L Thompson /// for i in 0..ne { 16108778c6fSJeremy L Thompson /// ind[2 * i + 0] = i as i32; 16208778c6fSJeremy L Thompson /// ind[2 * i + 1] = (i + 1) as i32; 16308778c6fSJeremy L Thompson /// } 16408778c6fSJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 16508778c6fSJeremy L Thompson /// let strides: [i32; 3] = [1, q as i32, q as i32]; 16608778c6fSJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, 2, 1, q * ne, strides)?; 16708778c6fSJeremy L Thompson /// 16808778c6fSJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 16908778c6fSJeremy L Thompson /// 17008778c6fSJeremy L Thompson /// // Operator fields 17108778c6fSJeremy L Thompson /// let op = ceed 17208778c6fSJeremy L Thompson /// .operator(&qf, QFunctionOpt::None, QFunctionOpt::None)? 17308778c6fSJeremy L Thompson /// .field("dx", &r, &b, VectorOpt::Active)? 17408778c6fSJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &b, VectorOpt::None)? 17508778c6fSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)?; 17608778c6fSJeremy L Thompson /// 17708778c6fSJeremy L Thompson /// let inputs = op.inputs()?; 17808778c6fSJeremy L Thompson /// 17908778c6fSJeremy L Thompson /// assert!(inputs[0].basis().is_some(), "Incorrect field Basis"); 18008778c6fSJeremy L Thompson /// if let BasisOpt::Some(b) = inputs[0].basis() { 18108778c6fSJeremy L Thompson /// assert_eq!( 18208778c6fSJeremy L Thompson /// b.num_quadrature_points(), 18308778c6fSJeremy L Thompson /// q, 18408778c6fSJeremy L Thompson /// "Incorrect field Basis number of quadrature points" 18508778c6fSJeremy L Thompson /// ); 18608778c6fSJeremy L Thompson /// } 18708778c6fSJeremy L Thompson /// assert!(inputs[1].basis().is_some(), "Incorrect field Basis"); 18808778c6fSJeremy L Thompson /// if let BasisOpt::Some(b) = inputs[0].basis() { 18908778c6fSJeremy L Thompson /// assert_eq!( 19008778c6fSJeremy L Thompson /// b.num_quadrature_points(), 19108778c6fSJeremy L Thompson /// q, 19208778c6fSJeremy L Thompson /// "Incorrect field Basis number of quadrature points" 19308778c6fSJeremy L Thompson /// ); 19408778c6fSJeremy L Thompson /// } 19508778c6fSJeremy L Thompson /// 19608778c6fSJeremy L Thompson /// let outputs = op.outputs()?; 19708778c6fSJeremy L Thompson /// 19808778c6fSJeremy L Thompson /// assert!(outputs[0].basis().is_collocated(), "Incorrect field Basis"); 19908778c6fSJeremy L Thompson /// # Ok(()) 20008778c6fSJeremy L Thompson /// # } 20108778c6fSJeremy L Thompson /// ``` 20208778c6fSJeremy L Thompson pub fn basis(&self) -> BasisOpt { 20308778c6fSJeremy L Thompson let mut ptr = std::ptr::null_mut(); 20408778c6fSJeremy L Thompson unsafe { 20508778c6fSJeremy L Thompson bind_ceed::CeedOperatorFieldGetBasis(self.ptr, &mut ptr); 20608778c6fSJeremy L Thompson } 20708778c6fSJeremy L Thompson if ptr == unsafe { bind_ceed::CEED_BASIS_COLLOCATED } { 20808778c6fSJeremy L Thompson BasisOpt::Collocated 20908778c6fSJeremy L Thompson } else { 21008778c6fSJeremy L Thompson let slice = unsafe { 21108778c6fSJeremy L Thompson std::slice::from_raw_parts( 21208778c6fSJeremy L Thompson &ptr as *const bind_ceed::CeedBasis as *const crate::Basis, 21308778c6fSJeremy L Thompson 1 as usize, 21408778c6fSJeremy L Thompson ) 21508778c6fSJeremy L Thompson }; 21608778c6fSJeremy L Thompson BasisOpt::Some(&slice[0]) 21708778c6fSJeremy L Thompson } 21808778c6fSJeremy L Thompson } 21908778c6fSJeremy L Thompson 22008778c6fSJeremy L Thompson /// Get the Vector of an OperatorField 22108778c6fSJeremy L Thompson /// 22208778c6fSJeremy L Thompson /// ``` 22308778c6fSJeremy L Thompson /// # use libceed::prelude::*; 2244d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 22508778c6fSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 22608778c6fSJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 22708778c6fSJeremy L Thompson /// 22808778c6fSJeremy L Thompson /// // Operator field arguments 22908778c6fSJeremy L Thompson /// let ne = 3; 23008778c6fSJeremy L Thompson /// let q = 4 as usize; 23108778c6fSJeremy L Thompson /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 23208778c6fSJeremy L Thompson /// for i in 0..ne { 23308778c6fSJeremy L Thompson /// ind[2 * i + 0] = i as i32; 23408778c6fSJeremy L Thompson /// ind[2 * i + 1] = (i + 1) as i32; 23508778c6fSJeremy L Thompson /// } 23608778c6fSJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 23708778c6fSJeremy L Thompson /// let strides: [i32; 3] = [1, q as i32, q as i32]; 23808778c6fSJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, 2, 1, q * ne, strides)?; 23908778c6fSJeremy L Thompson /// 24008778c6fSJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 24108778c6fSJeremy L Thompson /// 24208778c6fSJeremy L Thompson /// // Operator fields 24308778c6fSJeremy L Thompson /// let op = ceed 24408778c6fSJeremy L Thompson /// .operator(&qf, QFunctionOpt::None, QFunctionOpt::None)? 24508778c6fSJeremy L Thompson /// .field("dx", &r, &b, VectorOpt::Active)? 24608778c6fSJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &b, VectorOpt::None)? 24708778c6fSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)?; 24808778c6fSJeremy L Thompson /// 24908778c6fSJeremy L Thompson /// let inputs = op.inputs()?; 25008778c6fSJeremy L Thompson /// 25108778c6fSJeremy L Thompson /// assert!(inputs[0].vector().is_active(), "Incorrect field Vector"); 25208778c6fSJeremy L Thompson /// assert!(inputs[1].vector().is_none(), "Incorrect field Vector"); 25308778c6fSJeremy L Thompson /// # Ok(()) 25408778c6fSJeremy L Thompson /// # } 25508778c6fSJeremy L Thompson /// ``` 25608778c6fSJeremy L Thompson pub fn vector(&self) -> VectorOpt { 25708778c6fSJeremy L Thompson let mut ptr = std::ptr::null_mut(); 25808778c6fSJeremy L Thompson unsafe { 25908778c6fSJeremy L Thompson bind_ceed::CeedOperatorFieldGetVector(self.ptr, &mut ptr); 26008778c6fSJeremy L Thompson } 26108778c6fSJeremy L Thompson if ptr == unsafe { bind_ceed::CEED_VECTOR_ACTIVE } { 26208778c6fSJeremy L Thompson VectorOpt::Active 26308778c6fSJeremy L Thompson } else if ptr == unsafe { bind_ceed::CEED_VECTOR_NONE } { 26408778c6fSJeremy L Thompson VectorOpt::None 26508778c6fSJeremy L Thompson } else { 26608778c6fSJeremy L Thompson let slice = unsafe { 26708778c6fSJeremy L Thompson std::slice::from_raw_parts( 26808778c6fSJeremy L Thompson &ptr as *const bind_ceed::CeedVector as *const crate::Vector, 26908778c6fSJeremy L Thompson 1 as usize, 27008778c6fSJeremy L Thompson ) 27108778c6fSJeremy L Thompson }; 27208778c6fSJeremy L Thompson VectorOpt::Some(&slice[0]) 27308778c6fSJeremy L Thompson } 27408778c6fSJeremy L Thompson } 27508778c6fSJeremy L Thompson } 27608778c6fSJeremy L Thompson 27708778c6fSJeremy L Thompson // ----------------------------------------------------------------------------- 2789df49d7eSJed Brown // CeedOperator context wrapper 2799df49d7eSJed Brown // ----------------------------------------------------------------------------- 280c68be7a2SJeremy L Thompson #[derive(Debug)] 2819df49d7eSJed Brown pub(crate) struct OperatorCore<'a> { 2829df49d7eSJed Brown ptr: bind_ceed::CeedOperator, 2831142270cSJeremy L Thompson _lifeline: PhantomData<&'a ()>, 2849df49d7eSJed Brown } 2859df49d7eSJed Brown 286c68be7a2SJeremy L Thompson #[derive(Debug)] 2879df49d7eSJed Brown pub struct Operator<'a> { 2889df49d7eSJed Brown op_core: OperatorCore<'a>, 2899df49d7eSJed Brown } 2909df49d7eSJed Brown 291c68be7a2SJeremy L Thompson #[derive(Debug)] 2929df49d7eSJed Brown pub struct CompositeOperator<'a> { 2939df49d7eSJed Brown op_core: OperatorCore<'a>, 2949df49d7eSJed Brown } 2959df49d7eSJed Brown 2969df49d7eSJed Brown // ----------------------------------------------------------------------------- 2979df49d7eSJed Brown // Destructor 2989df49d7eSJed Brown // ----------------------------------------------------------------------------- 2999df49d7eSJed Brown impl<'a> Drop for OperatorCore<'a> { 3009df49d7eSJed Brown fn drop(&mut self) { 3019df49d7eSJed Brown unsafe { 3029df49d7eSJed Brown bind_ceed::CeedOperatorDestroy(&mut self.ptr); 3039df49d7eSJed Brown } 3049df49d7eSJed Brown } 3059df49d7eSJed Brown } 3069df49d7eSJed Brown 3079df49d7eSJed Brown // ----------------------------------------------------------------------------- 3089df49d7eSJed Brown // Display 3099df49d7eSJed Brown // ----------------------------------------------------------------------------- 3109df49d7eSJed Brown impl<'a> fmt::Display for OperatorCore<'a> { 3119df49d7eSJed Brown fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 3129df49d7eSJed Brown let mut ptr = std::ptr::null_mut(); 3139df49d7eSJed Brown let mut sizeloc = crate::MAX_BUFFER_LENGTH; 3149df49d7eSJed Brown let cstring = unsafe { 3159df49d7eSJed Brown let file = bind_ceed::open_memstream(&mut ptr, &mut sizeloc); 3169df49d7eSJed Brown bind_ceed::CeedOperatorView(self.ptr, file); 3179df49d7eSJed Brown bind_ceed::fclose(file); 3189df49d7eSJed Brown CString::from_raw(ptr) 3199df49d7eSJed Brown }; 3209df49d7eSJed Brown cstring.to_string_lossy().fmt(f) 3219df49d7eSJed Brown } 3229df49d7eSJed Brown } 3239df49d7eSJed Brown 3249df49d7eSJed Brown /// View an Operator 3259df49d7eSJed Brown /// 3269df49d7eSJed Brown /// ``` 3279df49d7eSJed Brown /// # use libceed::prelude::*; 3284d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 3299df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 330c68be7a2SJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 3319df49d7eSJed Brown /// 3329df49d7eSJed Brown /// // Operator field arguments 3339df49d7eSJed Brown /// let ne = 3; 3349df49d7eSJed Brown /// let q = 4 as usize; 3359df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 3369df49d7eSJed Brown /// for i in 0..ne { 3379df49d7eSJed Brown /// ind[2 * i + 0] = i as i32; 3389df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32; 3399df49d7eSJed Brown /// } 340c68be7a2SJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 3419df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 342c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, 2, 1, q * ne, strides)?; 3439df49d7eSJed Brown /// 344c68be7a2SJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 3459df49d7eSJed Brown /// 3469df49d7eSJed Brown /// // Operator fields 3479df49d7eSJed Brown /// let op = ceed 348c68be7a2SJeremy L Thompson /// .operator(&qf, QFunctionOpt::None, QFunctionOpt::None)? 349c68be7a2SJeremy L Thompson /// .field("dx", &r, &b, VectorOpt::Active)? 350c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &b, VectorOpt::None)? 351c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)?; 3529df49d7eSJed Brown /// 3539df49d7eSJed Brown /// println!("{}", op); 354c68be7a2SJeremy L Thompson /// # Ok(()) 355c68be7a2SJeremy L Thompson /// # } 3569df49d7eSJed Brown /// ``` 3579df49d7eSJed Brown impl<'a> fmt::Display for Operator<'a> { 3589df49d7eSJed Brown fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 3599df49d7eSJed Brown self.op_core.fmt(f) 3609df49d7eSJed Brown } 3619df49d7eSJed Brown } 3629df49d7eSJed Brown 3639df49d7eSJed Brown /// View a composite Operator 3649df49d7eSJed Brown /// 3659df49d7eSJed Brown /// ``` 3669df49d7eSJed Brown /// # use libceed::prelude::*; 3674d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 3689df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 3699df49d7eSJed Brown /// 3709df49d7eSJed Brown /// // Sub operator field arguments 3719df49d7eSJed Brown /// let ne = 3; 3729df49d7eSJed Brown /// let q = 4 as usize; 3739df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 3749df49d7eSJed Brown /// for i in 0..ne { 3759df49d7eSJed Brown /// ind[2 * i + 0] = i as i32; 3769df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32; 3779df49d7eSJed Brown /// } 378c68be7a2SJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 3799df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 380c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, 2, 1, q * ne, strides)?; 3819df49d7eSJed Brown /// 382c68be7a2SJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 3839df49d7eSJed Brown /// 384c68be7a2SJeremy L Thompson /// let qdata_mass = ceed.vector(q * ne)?; 385c68be7a2SJeremy L Thompson /// let qdata_diff = ceed.vector(q * ne)?; 3869df49d7eSJed Brown /// 387c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 3889df49d7eSJed Brown /// let op_mass = ceed 389c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 390c68be7a2SJeremy L Thompson /// .field("u", &r, &b, VectorOpt::Active)? 391c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, &qdata_mass)? 392c68be7a2SJeremy L Thompson /// .field("v", &r, &b, VectorOpt::Active)?; 3939df49d7eSJed Brown /// 394c68be7a2SJeremy L Thompson /// let qf_diff = ceed.q_function_interior_by_name("Poisson1DApply")?; 3959df49d7eSJed Brown /// let op_diff = ceed 396c68be7a2SJeremy L Thompson /// .operator(&qf_diff, QFunctionOpt::None, QFunctionOpt::None)? 397c68be7a2SJeremy L Thompson /// .field("du", &r, &b, VectorOpt::Active)? 398c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, &qdata_diff)? 399c68be7a2SJeremy L Thompson /// .field("dv", &r, &b, VectorOpt::Active)?; 4009df49d7eSJed Brown /// 4019df49d7eSJed Brown /// let op = ceed 402c68be7a2SJeremy L Thompson /// .composite_operator()? 403c68be7a2SJeremy L Thompson /// .sub_operator(&op_mass)? 404c68be7a2SJeremy L Thompson /// .sub_operator(&op_diff)?; 4059df49d7eSJed Brown /// 4069df49d7eSJed Brown /// println!("{}", op); 407c68be7a2SJeremy L Thompson /// # Ok(()) 408c68be7a2SJeremy L Thompson /// # } 4099df49d7eSJed Brown /// ``` 4109df49d7eSJed Brown impl<'a> fmt::Display for CompositeOperator<'a> { 4119df49d7eSJed Brown fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 4129df49d7eSJed Brown self.op_core.fmt(f) 4139df49d7eSJed Brown } 4149df49d7eSJed Brown } 4159df49d7eSJed Brown 4169df49d7eSJed Brown // ----------------------------------------------------------------------------- 4179df49d7eSJed Brown // Core functionality 4189df49d7eSJed Brown // ----------------------------------------------------------------------------- 4199df49d7eSJed Brown impl<'a> OperatorCore<'a> { 4201142270cSJeremy L Thompson // Error handling 4211142270cSJeremy L Thompson #[doc(hidden)] 4221142270cSJeremy L Thompson fn check_error(&self, ierr: i32) -> crate::Result<i32> { 4231142270cSJeremy L Thompson let mut ptr = std::ptr::null_mut(); 4241142270cSJeremy L Thompson unsafe { 4251142270cSJeremy L Thompson bind_ceed::CeedOperatorGetCeed(self.ptr, &mut ptr); 4261142270cSJeremy L Thompson } 4271142270cSJeremy L Thompson crate::check_error(ptr, ierr) 4281142270cSJeremy L Thompson } 4291142270cSJeremy L Thompson 4309df49d7eSJed Brown // Common implementations 431*6f97ff0aSJeremy L Thompson pub fn check(&self) -> crate::Result<i32> { 432*6f97ff0aSJeremy L Thompson let ierr = unsafe { bind_ceed::CeedOperatorCheckReady(self.ptr) }; 433*6f97ff0aSJeremy L Thompson self.check_error(ierr) 434*6f97ff0aSJeremy L Thompson } 435*6f97ff0aSJeremy L Thompson 4369df49d7eSJed Brown pub fn apply(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> { 4379df49d7eSJed Brown let ierr = unsafe { 4389df49d7eSJed Brown bind_ceed::CeedOperatorApply( 4399df49d7eSJed Brown self.ptr, 4409df49d7eSJed Brown input.ptr, 4419df49d7eSJed Brown output.ptr, 4429df49d7eSJed Brown bind_ceed::CEED_REQUEST_IMMEDIATE, 4439df49d7eSJed Brown ) 4449df49d7eSJed Brown }; 4451142270cSJeremy L Thompson self.check_error(ierr) 4469df49d7eSJed Brown } 4479df49d7eSJed Brown 4489df49d7eSJed Brown pub fn apply_add(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> { 4499df49d7eSJed Brown let ierr = unsafe { 4509df49d7eSJed Brown bind_ceed::CeedOperatorApplyAdd( 4519df49d7eSJed Brown self.ptr, 4529df49d7eSJed Brown input.ptr, 4539df49d7eSJed Brown output.ptr, 4549df49d7eSJed Brown bind_ceed::CEED_REQUEST_IMMEDIATE, 4559df49d7eSJed Brown ) 4569df49d7eSJed Brown }; 4571142270cSJeremy L Thompson self.check_error(ierr) 4589df49d7eSJed Brown } 4599df49d7eSJed Brown 4609df49d7eSJed Brown pub fn linear_assemble_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> { 4619df49d7eSJed Brown let ierr = unsafe { 4629df49d7eSJed Brown bind_ceed::CeedOperatorLinearAssembleDiagonal( 4639df49d7eSJed Brown self.ptr, 4649df49d7eSJed Brown assembled.ptr, 4659df49d7eSJed Brown bind_ceed::CEED_REQUEST_IMMEDIATE, 4669df49d7eSJed Brown ) 4679df49d7eSJed Brown }; 4681142270cSJeremy L Thompson self.check_error(ierr) 4699df49d7eSJed Brown } 4709df49d7eSJed Brown 4719df49d7eSJed Brown pub fn linear_assemble_add_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> { 4729df49d7eSJed Brown let ierr = unsafe { 4739df49d7eSJed Brown bind_ceed::CeedOperatorLinearAssembleAddDiagonal( 4749df49d7eSJed Brown self.ptr, 4759df49d7eSJed Brown assembled.ptr, 4769df49d7eSJed Brown bind_ceed::CEED_REQUEST_IMMEDIATE, 4779df49d7eSJed Brown ) 4789df49d7eSJed Brown }; 4791142270cSJeremy L Thompson self.check_error(ierr) 4809df49d7eSJed Brown } 4819df49d7eSJed Brown 4829df49d7eSJed Brown pub fn linear_assemble_point_block_diagonal( 4839df49d7eSJed Brown &self, 4849df49d7eSJed Brown assembled: &mut Vector, 4859df49d7eSJed Brown ) -> crate::Result<i32> { 4869df49d7eSJed Brown let ierr = unsafe { 4879df49d7eSJed Brown bind_ceed::CeedOperatorLinearAssemblePointBlockDiagonal( 4889df49d7eSJed Brown self.ptr, 4899df49d7eSJed Brown assembled.ptr, 4909df49d7eSJed Brown bind_ceed::CEED_REQUEST_IMMEDIATE, 4919df49d7eSJed Brown ) 4929df49d7eSJed Brown }; 4931142270cSJeremy L Thompson self.check_error(ierr) 4949df49d7eSJed Brown } 4959df49d7eSJed Brown 4969df49d7eSJed Brown pub fn linear_assemble_add_point_block_diagonal( 4979df49d7eSJed Brown &self, 4989df49d7eSJed Brown assembled: &mut Vector, 4999df49d7eSJed Brown ) -> crate::Result<i32> { 5009df49d7eSJed Brown let ierr = unsafe { 5019df49d7eSJed Brown bind_ceed::CeedOperatorLinearAssembleAddPointBlockDiagonal( 5029df49d7eSJed Brown self.ptr, 5039df49d7eSJed Brown assembled.ptr, 5049df49d7eSJed Brown bind_ceed::CEED_REQUEST_IMMEDIATE, 5059df49d7eSJed Brown ) 5069df49d7eSJed Brown }; 5071142270cSJeremy L Thompson self.check_error(ierr) 5089df49d7eSJed Brown } 5099df49d7eSJed Brown } 5109df49d7eSJed Brown 5119df49d7eSJed Brown // ----------------------------------------------------------------------------- 5129df49d7eSJed Brown // Operator 5139df49d7eSJed Brown // ----------------------------------------------------------------------------- 5149df49d7eSJed Brown impl<'a> Operator<'a> { 5159df49d7eSJed Brown // Constructor 5169df49d7eSJed Brown pub fn create<'b>( 5179df49d7eSJed Brown ceed: &'a crate::Ceed, 5189df49d7eSJed Brown qf: impl Into<QFunctionOpt<'b>>, 5199df49d7eSJed Brown dqf: impl Into<QFunctionOpt<'b>>, 5209df49d7eSJed Brown dqfT: impl Into<QFunctionOpt<'b>>, 5219df49d7eSJed Brown ) -> crate::Result<Self> { 5229df49d7eSJed Brown let mut ptr = std::ptr::null_mut(); 5239df49d7eSJed Brown let ierr = unsafe { 5249df49d7eSJed Brown bind_ceed::CeedOperatorCreate( 5259df49d7eSJed Brown ceed.ptr, 5269df49d7eSJed Brown qf.into().to_raw(), 5279df49d7eSJed Brown dqf.into().to_raw(), 5289df49d7eSJed Brown dqfT.into().to_raw(), 5299df49d7eSJed Brown &mut ptr, 5309df49d7eSJed Brown ) 5319df49d7eSJed Brown }; 5329df49d7eSJed Brown ceed.check_error(ierr)?; 5339df49d7eSJed Brown Ok(Self { 5341142270cSJeremy L Thompson op_core: OperatorCore { 5351142270cSJeremy L Thompson ptr, 5361142270cSJeremy L Thompson _lifeline: PhantomData, 5371142270cSJeremy L Thompson }, 5389df49d7eSJed Brown }) 5399df49d7eSJed Brown } 5409df49d7eSJed Brown 5411142270cSJeremy L Thompson fn from_raw(ptr: bind_ceed::CeedOperator) -> crate::Result<Self> { 5429df49d7eSJed Brown Ok(Self { 5431142270cSJeremy L Thompson op_core: OperatorCore { 5441142270cSJeremy L Thompson ptr, 5451142270cSJeremy L Thompson _lifeline: PhantomData, 5461142270cSJeremy L Thompson }, 5479df49d7eSJed Brown }) 5489df49d7eSJed Brown } 5499df49d7eSJed Brown 5509df49d7eSJed Brown /// Apply Operator to a vector 5519df49d7eSJed Brown /// 5529df49d7eSJed Brown /// * `input` - Input Vector 5539df49d7eSJed Brown /// * `output` - Output Vector 5549df49d7eSJed Brown /// 5559df49d7eSJed Brown /// ``` 5569df49d7eSJed Brown /// # use libceed::prelude::*; 5574d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 5589df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 5599df49d7eSJed Brown /// let ne = 4; 5609df49d7eSJed Brown /// let p = 3; 5619df49d7eSJed Brown /// let q = 4; 5629df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 5639df49d7eSJed Brown /// 5649df49d7eSJed Brown /// // Vectors 565c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0])?; 566c68be7a2SJeremy L Thompson /// let mut qdata = ceed.vector(ne * q)?; 5679df49d7eSJed Brown /// qdata.set_value(0.0); 568c68be7a2SJeremy L Thompson /// let u = ceed.vector_from_slice(&vec![1.0; ndofs])?; 569c68be7a2SJeremy L Thompson /// let mut v = ceed.vector(ndofs)?; 5709df49d7eSJed Brown /// v.set_value(0.0); 5719df49d7eSJed Brown /// 5729df49d7eSJed Brown /// // Restrictions 5739df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 5749df49d7eSJed Brown /// for i in 0..ne { 5759df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 5769df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 5779df49d7eSJed Brown /// } 578c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 5799df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 5809df49d7eSJed Brown /// for i in 0..ne { 5819df49d7eSJed Brown /// indu[p * i + 0] = i as i32; 5829df49d7eSJed Brown /// indu[p * i + 1] = (i + 1) as i32; 5839df49d7eSJed Brown /// indu[p * i + 2] = (i + 2) as i32; 5849df49d7eSJed Brown /// } 585c68be7a2SJeremy L Thompson /// let ru = ceed.elem_restriction(ne, 3, 1, 1, ndofs, MemType::Host, &indu)?; 5869df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 587c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 5889df49d7eSJed Brown /// 5899df49d7eSJed Brown /// // Bases 590c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 591c68be7a2SJeremy L Thompson /// let bu = ceed.basis_tensor_H1_Lagrange(1, 1, p, q, QuadMode::Gauss)?; 5929df49d7eSJed Brown /// 5939df49d7eSJed Brown /// // Build quadrature data 594c68be7a2SJeremy L Thompson /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 595c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 596c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 597c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 598c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)? 599c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata)?; 6009df49d7eSJed Brown /// 6019df49d7eSJed Brown /// // Mass operator 602c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 6039df49d7eSJed Brown /// let op_mass = ceed 604c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 605c68be7a2SJeremy L Thompson /// .field("u", &ru, &bu, VectorOpt::Active)? 606c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, &qdata)? 607c68be7a2SJeremy L Thompson /// .field("v", &ru, &bu, VectorOpt::Active)?; 6089df49d7eSJed Brown /// 6099df49d7eSJed Brown /// v.set_value(0.0); 610c68be7a2SJeremy L Thompson /// op_mass.apply(&u, &mut v)?; 6119df49d7eSJed Brown /// 6129df49d7eSJed Brown /// // Check 613e78171edSJeremy L Thompson /// let sum: Scalar = v.view()?.iter().sum(); 6149df49d7eSJed Brown /// assert!( 61580a9ef05SNatalie Beams /// (sum - 2.0).abs() < 10.0 * libceed::EPSILON, 6169df49d7eSJed Brown /// "Incorrect interval length computed" 6179df49d7eSJed Brown /// ); 618c68be7a2SJeremy L Thompson /// # Ok(()) 619c68be7a2SJeremy L Thompson /// # } 6209df49d7eSJed Brown /// ``` 6219df49d7eSJed Brown pub fn apply(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> { 6229df49d7eSJed Brown self.op_core.apply(input, output) 6239df49d7eSJed Brown } 6249df49d7eSJed Brown 6259df49d7eSJed Brown /// Apply Operator to a vector and add result to output vector 6269df49d7eSJed Brown /// 6279df49d7eSJed Brown /// * `input` - Input Vector 6289df49d7eSJed Brown /// * `output` - Output Vector 6299df49d7eSJed Brown /// 6309df49d7eSJed Brown /// ``` 6319df49d7eSJed Brown /// # use libceed::prelude::*; 6324d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 6339df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 6349df49d7eSJed Brown /// let ne = 4; 6359df49d7eSJed Brown /// let p = 3; 6369df49d7eSJed Brown /// let q = 4; 6379df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 6389df49d7eSJed Brown /// 6399df49d7eSJed Brown /// // Vectors 640c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0])?; 641c68be7a2SJeremy L Thompson /// let mut qdata = ceed.vector(ne * q)?; 6429df49d7eSJed Brown /// qdata.set_value(0.0); 643c68be7a2SJeremy L Thompson /// let u = ceed.vector_from_slice(&vec![1.0; ndofs])?; 644c68be7a2SJeremy L Thompson /// let mut v = ceed.vector(ndofs)?; 6459df49d7eSJed Brown /// 6469df49d7eSJed Brown /// // Restrictions 6479df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 6489df49d7eSJed Brown /// for i in 0..ne { 6499df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 6509df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 6519df49d7eSJed Brown /// } 652c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 6539df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 6549df49d7eSJed Brown /// for i in 0..ne { 6559df49d7eSJed Brown /// indu[p * i + 0] = i as i32; 6569df49d7eSJed Brown /// indu[p * i + 1] = (i + 1) as i32; 6579df49d7eSJed Brown /// indu[p * i + 2] = (i + 2) as i32; 6589df49d7eSJed Brown /// } 659c68be7a2SJeremy L Thompson /// let ru = ceed.elem_restriction(ne, 3, 1, 1, ndofs, MemType::Host, &indu)?; 6609df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 661c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 6629df49d7eSJed Brown /// 6639df49d7eSJed Brown /// // Bases 664c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 665c68be7a2SJeremy L Thompson /// let bu = ceed.basis_tensor_H1_Lagrange(1, 1, p, q, QuadMode::Gauss)?; 6669df49d7eSJed Brown /// 6679df49d7eSJed Brown /// // Build quadrature data 668c68be7a2SJeremy L Thompson /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 669c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 670c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 671c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 672c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)? 673c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata)?; 6749df49d7eSJed Brown /// 6759df49d7eSJed Brown /// // Mass operator 676c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 6779df49d7eSJed Brown /// let op_mass = ceed 678c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 679c68be7a2SJeremy L Thompson /// .field("u", &ru, &bu, VectorOpt::Active)? 680c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, &qdata)? 681c68be7a2SJeremy L Thompson /// .field("v", &ru, &bu, VectorOpt::Active)?; 6829df49d7eSJed Brown /// 6839df49d7eSJed Brown /// v.set_value(1.0); 684c68be7a2SJeremy L Thompson /// op_mass.apply_add(&u, &mut v)?; 6859df49d7eSJed Brown /// 6869df49d7eSJed Brown /// // Check 687e78171edSJeremy L Thompson /// let sum: Scalar = v.view()?.iter().sum(); 6889df49d7eSJed Brown /// assert!( 68980a9ef05SNatalie Beams /// (sum - (2.0 + ndofs as Scalar)).abs() < 10.0 * libceed::EPSILON, 6909df49d7eSJed Brown /// "Incorrect interval length computed and added" 6919df49d7eSJed Brown /// ); 692c68be7a2SJeremy L Thompson /// # Ok(()) 693c68be7a2SJeremy L Thompson /// # } 6949df49d7eSJed Brown /// ``` 6959df49d7eSJed Brown pub fn apply_add(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> { 6969df49d7eSJed Brown self.op_core.apply_add(input, output) 6979df49d7eSJed Brown } 6989df49d7eSJed Brown 6999df49d7eSJed Brown /// Provide a field to a Operator for use by its QFunction 7009df49d7eSJed Brown /// 7019df49d7eSJed Brown /// * `fieldname` - Name of the field (to be matched with the name used by 7029df49d7eSJed Brown /// the QFunction) 7039df49d7eSJed Brown /// * `r` - ElemRestriction 7049df49d7eSJed Brown /// * `b` - Basis in which the field resides or `BasisCollocated` if 7059df49d7eSJed Brown /// collocated with quadrature points 7069df49d7eSJed Brown /// * `v` - Vector to be used by Operator or `VectorActive` if field 7079df49d7eSJed Brown /// is active or `VectorNone` if using `Weight` with the 7089df49d7eSJed Brown /// QFunction 7099df49d7eSJed Brown /// 7109df49d7eSJed Brown /// 7119df49d7eSJed Brown /// ``` 7129df49d7eSJed Brown /// # use libceed::prelude::*; 7134d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 7149df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 715c68be7a2SJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 716c68be7a2SJeremy L Thompson /// let mut op = ceed.operator(&qf, QFunctionOpt::None, QFunctionOpt::None)?; 7179df49d7eSJed Brown /// 7189df49d7eSJed Brown /// // Operator field arguments 7199df49d7eSJed Brown /// let ne = 3; 7209df49d7eSJed Brown /// let q = 4; 7219df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 7229df49d7eSJed Brown /// for i in 0..ne { 7239df49d7eSJed Brown /// ind[2 * i + 0] = i as i32; 7249df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32; 7259df49d7eSJed Brown /// } 726c68be7a2SJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 7279df49d7eSJed Brown /// 728c68be7a2SJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 7299df49d7eSJed Brown /// 7309df49d7eSJed Brown /// // Operator field 731c68be7a2SJeremy L Thompson /// op = op.field("dx", &r, &b, VectorOpt::Active)?; 732c68be7a2SJeremy L Thompson /// # Ok(()) 733c68be7a2SJeremy L Thompson /// # } 7349df49d7eSJed Brown /// ``` 7359df49d7eSJed Brown #[allow(unused_mut)] 7369df49d7eSJed Brown pub fn field<'b>( 7379df49d7eSJed Brown mut self, 7389df49d7eSJed Brown fieldname: &str, 7399df49d7eSJed Brown r: impl Into<ElemRestrictionOpt<'b>>, 7409df49d7eSJed Brown b: impl Into<BasisOpt<'b>>, 7419df49d7eSJed Brown v: impl Into<VectorOpt<'b>>, 7429df49d7eSJed Brown ) -> crate::Result<Self> { 7439df49d7eSJed Brown let fieldname = CString::new(fieldname).expect("CString::new failed"); 7449df49d7eSJed Brown let fieldname = fieldname.as_ptr() as *const i8; 7459df49d7eSJed Brown let ierr = unsafe { 7469df49d7eSJed Brown bind_ceed::CeedOperatorSetField( 7479df49d7eSJed Brown self.op_core.ptr, 7489df49d7eSJed Brown fieldname, 7499df49d7eSJed Brown r.into().to_raw(), 7509df49d7eSJed Brown b.into().to_raw(), 7519df49d7eSJed Brown v.into().to_raw(), 7529df49d7eSJed Brown ) 7539df49d7eSJed Brown }; 7541142270cSJeremy L Thompson self.op_core.check_error(ierr)?; 7559df49d7eSJed Brown Ok(self) 7569df49d7eSJed Brown } 7579df49d7eSJed Brown 75808778c6fSJeremy L Thompson /// Get a slice of Operator inputs 75908778c6fSJeremy L Thompson /// 76008778c6fSJeremy L Thompson /// ``` 76108778c6fSJeremy L Thompson /// # use libceed::prelude::*; 7624d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 76308778c6fSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 76408778c6fSJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 76508778c6fSJeremy L Thompson /// 76608778c6fSJeremy L Thompson /// // Operator field arguments 76708778c6fSJeremy L Thompson /// let ne = 3; 76808778c6fSJeremy L Thompson /// let q = 4 as usize; 76908778c6fSJeremy L Thompson /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 77008778c6fSJeremy L Thompson /// for i in 0..ne { 77108778c6fSJeremy L Thompson /// ind[2 * i + 0] = i as i32; 77208778c6fSJeremy L Thompson /// ind[2 * i + 1] = (i + 1) as i32; 77308778c6fSJeremy L Thompson /// } 77408778c6fSJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 77508778c6fSJeremy L Thompson /// let strides: [i32; 3] = [1, q as i32, q as i32]; 77608778c6fSJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, 2, 1, q * ne, strides)?; 77708778c6fSJeremy L Thompson /// 77808778c6fSJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 77908778c6fSJeremy L Thompson /// 78008778c6fSJeremy L Thompson /// // Operator fields 78108778c6fSJeremy L Thompson /// let op = ceed 78208778c6fSJeremy L Thompson /// .operator(&qf, QFunctionOpt::None, QFunctionOpt::None)? 78308778c6fSJeremy L Thompson /// .field("dx", &r, &b, VectorOpt::Active)? 78408778c6fSJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &b, VectorOpt::None)? 78508778c6fSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)?; 78608778c6fSJeremy L Thompson /// 78708778c6fSJeremy L Thompson /// let inputs = op.inputs()?; 78808778c6fSJeremy L Thompson /// 78908778c6fSJeremy L Thompson /// assert_eq!(inputs.len(), 2, "Incorrect inputs array"); 79008778c6fSJeremy L Thompson /// # Ok(()) 79108778c6fSJeremy L Thompson /// # } 79208778c6fSJeremy L Thompson /// ``` 79308778c6fSJeremy L Thompson pub fn inputs(&self) -> crate::Result<&[crate::OperatorField]> { 79408778c6fSJeremy L Thompson // Get array of raw C pointers for inputs 79508778c6fSJeremy L Thompson let mut num_inputs = 0; 79608778c6fSJeremy L Thompson let mut inputs_ptr = std::ptr::null_mut(); 79708778c6fSJeremy L Thompson let ierr = unsafe { 79808778c6fSJeremy L Thompson bind_ceed::CeedOperatorGetFields( 79908778c6fSJeremy L Thompson self.op_core.ptr, 80008778c6fSJeremy L Thompson &mut num_inputs, 80108778c6fSJeremy L Thompson &mut inputs_ptr, 80208778c6fSJeremy L Thompson std::ptr::null_mut() as *mut bind_ceed::CeedInt, 80308778c6fSJeremy L Thompson std::ptr::null_mut() as *mut *mut bind_ceed::CeedOperatorField, 80408778c6fSJeremy L Thompson ) 80508778c6fSJeremy L Thompson }; 80608778c6fSJeremy L Thompson self.op_core.check_error(ierr)?; 80708778c6fSJeremy L Thompson // Convert raw C pointers to fixed length slice 80808778c6fSJeremy L Thompson let inputs_slice = unsafe { 80908778c6fSJeremy L Thompson std::slice::from_raw_parts( 81008778c6fSJeremy L Thompson inputs_ptr as *const crate::OperatorField, 81108778c6fSJeremy L Thompson num_inputs as usize, 81208778c6fSJeremy L Thompson ) 81308778c6fSJeremy L Thompson }; 81408778c6fSJeremy L Thompson Ok(inputs_slice) 81508778c6fSJeremy L Thompson } 81608778c6fSJeremy L Thompson 81708778c6fSJeremy L Thompson /// Get a slice of Operator outputs 81808778c6fSJeremy L Thompson /// 81908778c6fSJeremy L Thompson /// ``` 82008778c6fSJeremy L Thompson /// # use libceed::prelude::*; 8214d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 82208778c6fSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 82308778c6fSJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 82408778c6fSJeremy L Thompson /// 82508778c6fSJeremy L Thompson /// // Operator field arguments 82608778c6fSJeremy L Thompson /// let ne = 3; 82708778c6fSJeremy L Thompson /// let q = 4 as usize; 82808778c6fSJeremy L Thompson /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 82908778c6fSJeremy L Thompson /// for i in 0..ne { 83008778c6fSJeremy L Thompson /// ind[2 * i + 0] = i as i32; 83108778c6fSJeremy L Thompson /// ind[2 * i + 1] = (i + 1) as i32; 83208778c6fSJeremy L Thompson /// } 83308778c6fSJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 83408778c6fSJeremy L Thompson /// let strides: [i32; 3] = [1, q as i32, q as i32]; 83508778c6fSJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, 2, 1, q * ne, strides)?; 83608778c6fSJeremy L Thompson /// 83708778c6fSJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 83808778c6fSJeremy L Thompson /// 83908778c6fSJeremy L Thompson /// // Operator fields 84008778c6fSJeremy L Thompson /// let op = ceed 84108778c6fSJeremy L Thompson /// .operator(&qf, QFunctionOpt::None, QFunctionOpt::None)? 84208778c6fSJeremy L Thompson /// .field("dx", &r, &b, VectorOpt::Active)? 84308778c6fSJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &b, VectorOpt::None)? 84408778c6fSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)?; 84508778c6fSJeremy L Thompson /// 84608778c6fSJeremy L Thompson /// let outputs = op.outputs()?; 84708778c6fSJeremy L Thompson /// 84808778c6fSJeremy L Thompson /// assert_eq!(outputs.len(), 1, "Incorrect outputs array"); 84908778c6fSJeremy L Thompson /// # Ok(()) 85008778c6fSJeremy L Thompson /// # } 85108778c6fSJeremy L Thompson /// ``` 85208778c6fSJeremy L Thompson pub fn outputs(&self) -> crate::Result<&[crate::OperatorField]> { 85308778c6fSJeremy L Thompson // Get array of raw C pointers for outputs 85408778c6fSJeremy L Thompson let mut num_outputs = 0; 85508778c6fSJeremy L Thompson let mut outputs_ptr = std::ptr::null_mut(); 85608778c6fSJeremy L Thompson let ierr = unsafe { 85708778c6fSJeremy L Thompson bind_ceed::CeedOperatorGetFields( 85808778c6fSJeremy L Thompson self.op_core.ptr, 85908778c6fSJeremy L Thompson std::ptr::null_mut() as *mut bind_ceed::CeedInt, 86008778c6fSJeremy L Thompson std::ptr::null_mut() as *mut *mut bind_ceed::CeedOperatorField, 86108778c6fSJeremy L Thompson &mut num_outputs, 86208778c6fSJeremy L Thompson &mut outputs_ptr, 86308778c6fSJeremy L Thompson ) 86408778c6fSJeremy L Thompson }; 86508778c6fSJeremy L Thompson self.op_core.check_error(ierr)?; 86608778c6fSJeremy L Thompson // Convert raw C pointers to fixed length slice 86708778c6fSJeremy L Thompson let outputs_slice = unsafe { 86808778c6fSJeremy L Thompson std::slice::from_raw_parts( 86908778c6fSJeremy L Thompson outputs_ptr as *const crate::OperatorField, 87008778c6fSJeremy L Thompson num_outputs as usize, 87108778c6fSJeremy L Thompson ) 87208778c6fSJeremy L Thompson }; 87308778c6fSJeremy L Thompson Ok(outputs_slice) 87408778c6fSJeremy L Thompson } 87508778c6fSJeremy L Thompson 876*6f97ff0aSJeremy L Thompson /// Check if Operator is setup correctly 877*6f97ff0aSJeremy L Thompson /// 878*6f97ff0aSJeremy L Thompson /// ``` 879*6f97ff0aSJeremy L Thompson /// # use libceed::prelude::*; 880*6f97ff0aSJeremy L Thompson /// # fn main() -> libceed::Result<()> { 881*6f97ff0aSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 882*6f97ff0aSJeremy L Thompson /// let ne = 4; 883*6f97ff0aSJeremy L Thompson /// let p = 3; 884*6f97ff0aSJeremy L Thompson /// let q = 4; 885*6f97ff0aSJeremy L Thompson /// let ndofs = p * ne - ne + 1; 886*6f97ff0aSJeremy L Thompson /// 887*6f97ff0aSJeremy L Thompson /// // Restrictions 888*6f97ff0aSJeremy L Thompson /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 889*6f97ff0aSJeremy L Thompson /// for i in 0..ne { 890*6f97ff0aSJeremy L Thompson /// indx[2 * i + 0] = i as i32; 891*6f97ff0aSJeremy L Thompson /// indx[2 * i + 1] = (i + 1) as i32; 892*6f97ff0aSJeremy L Thompson /// } 893*6f97ff0aSJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 894*6f97ff0aSJeremy L Thompson /// let strides: [i32; 3] = [1, q as i32, q as i32]; 895*6f97ff0aSJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 896*6f97ff0aSJeremy L Thompson /// 897*6f97ff0aSJeremy L Thompson /// // Bases 898*6f97ff0aSJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 899*6f97ff0aSJeremy L Thompson /// 900*6f97ff0aSJeremy L Thompson /// // Build quadrature data 901*6f97ff0aSJeremy L Thompson /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 902*6f97ff0aSJeremy L Thompson /// let op_build = ceed 903*6f97ff0aSJeremy L Thompson /// .operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 904*6f97ff0aSJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 905*6f97ff0aSJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 906*6f97ff0aSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)?; 907*6f97ff0aSJeremy L Thompson /// 908*6f97ff0aSJeremy L Thompson /// // Check 909*6f97ff0aSJeremy L Thompson /// assert!(op_build.check().is_ok(), "Operator setup incorrectly"); 910*6f97ff0aSJeremy L Thompson /// # Ok(()) 911*6f97ff0aSJeremy L Thompson /// # } 912*6f97ff0aSJeremy L Thompson /// ``` 913*6f97ff0aSJeremy L Thompson pub fn check(self) -> crate::Result<Self> { 914*6f97ff0aSJeremy L Thompson self.op_core.check()?; 915*6f97ff0aSJeremy L Thompson Ok(self) 916*6f97ff0aSJeremy L Thompson } 917*6f97ff0aSJeremy L Thompson 9183f2759cfSJeremy L Thompson /// Get the number of elements associated with an Operator 9193f2759cfSJeremy L Thompson /// 9203f2759cfSJeremy L Thompson /// 9213f2759cfSJeremy L Thompson /// ``` 9223f2759cfSJeremy L Thompson /// # use libceed::prelude::*; 9234d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 9243f2759cfSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 9253f2759cfSJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 9263f2759cfSJeremy L Thompson /// let mut op = ceed.operator(&qf, QFunctionOpt::None, QFunctionOpt::None)?; 9273f2759cfSJeremy L Thompson /// 9283f2759cfSJeremy L Thompson /// // Operator field arguments 9293f2759cfSJeremy L Thompson /// let ne = 3; 9303f2759cfSJeremy L Thompson /// let q = 4; 9313f2759cfSJeremy L Thompson /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 9323f2759cfSJeremy L Thompson /// for i in 0..ne { 9333f2759cfSJeremy L Thompson /// ind[2 * i + 0] = i as i32; 9343f2759cfSJeremy L Thompson /// ind[2 * i + 1] = (i + 1) as i32; 9353f2759cfSJeremy L Thompson /// } 9363f2759cfSJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 9373f2759cfSJeremy L Thompson /// 9383f2759cfSJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 9393f2759cfSJeremy L Thompson /// 9403f2759cfSJeremy L Thompson /// // Operator field 9413f2759cfSJeremy L Thompson /// op = op.field("dx", &r, &b, VectorOpt::Active)?; 9423f2759cfSJeremy L Thompson /// 9433f2759cfSJeremy L Thompson /// // Check number of elements 9443f2759cfSJeremy L Thompson /// assert_eq!(op.num_elements(), ne, "Incorrect number of elements"); 9453f2759cfSJeremy L Thompson /// # Ok(()) 9463f2759cfSJeremy L Thompson /// # } 9473f2759cfSJeremy L Thompson /// ``` 9483f2759cfSJeremy L Thompson pub fn num_elements(&self) -> usize { 9493f2759cfSJeremy L Thompson let mut nelem = 0; 9503f2759cfSJeremy L Thompson unsafe { bind_ceed::CeedOperatorGetNumElements(self.op_core.ptr, &mut nelem) }; 9513f2759cfSJeremy L Thompson usize::try_from(nelem).unwrap() 9523f2759cfSJeremy L Thompson } 9533f2759cfSJeremy L Thompson 9543f2759cfSJeremy L Thompson /// Get the number of quadrature points associated with each element of 9553f2759cfSJeremy L Thompson /// an Operator 9563f2759cfSJeremy L Thompson /// 9573f2759cfSJeremy L Thompson /// 9583f2759cfSJeremy L Thompson /// ``` 9593f2759cfSJeremy L Thompson /// # use libceed::prelude::*; 9604d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 9613f2759cfSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 9623f2759cfSJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 9633f2759cfSJeremy L Thompson /// let mut op = ceed.operator(&qf, QFunctionOpt::None, QFunctionOpt::None)?; 9643f2759cfSJeremy L Thompson /// 9653f2759cfSJeremy L Thompson /// // Operator field arguments 9663f2759cfSJeremy L Thompson /// let ne = 3; 9673f2759cfSJeremy L Thompson /// let q = 4; 9683f2759cfSJeremy L Thompson /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 9693f2759cfSJeremy L Thompson /// for i in 0..ne { 9703f2759cfSJeremy L Thompson /// ind[2 * i + 0] = i as i32; 9713f2759cfSJeremy L Thompson /// ind[2 * i + 1] = (i + 1) as i32; 9723f2759cfSJeremy L Thompson /// } 9733f2759cfSJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 9743f2759cfSJeremy L Thompson /// 9753f2759cfSJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 9763f2759cfSJeremy L Thompson /// 9773f2759cfSJeremy L Thompson /// // Operator field 9783f2759cfSJeremy L Thompson /// op = op.field("dx", &r, &b, VectorOpt::Active)?; 9793f2759cfSJeremy L Thompson /// 9803f2759cfSJeremy L Thompson /// // Check number of quadrature points 9813f2759cfSJeremy L Thompson /// assert_eq!( 9823f2759cfSJeremy L Thompson /// op.num_quadrature_points(), 9833f2759cfSJeremy L Thompson /// q, 9843f2759cfSJeremy L Thompson /// "Incorrect number of quadrature points" 9853f2759cfSJeremy L Thompson /// ); 9863f2759cfSJeremy L Thompson /// # Ok(()) 9873f2759cfSJeremy L Thompson /// # } 9883f2759cfSJeremy L Thompson /// ``` 9893f2759cfSJeremy L Thompson pub fn num_quadrature_points(&self) -> usize { 9903f2759cfSJeremy L Thompson let mut Q = 0; 9913f2759cfSJeremy L Thompson unsafe { bind_ceed::CeedOperatorGetNumQuadraturePoints(self.op_core.ptr, &mut Q) }; 9923f2759cfSJeremy L Thompson usize::try_from(Q).unwrap() 9933f2759cfSJeremy L Thompson } 9943f2759cfSJeremy L Thompson 9959df49d7eSJed Brown /// Assemble the diagonal of a square linear Operator 9969df49d7eSJed Brown /// 9979df49d7eSJed Brown /// This overwrites a Vector with the diagonal of a linear Operator. 9989df49d7eSJed Brown /// 9999df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 10009df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 10019df49d7eSJed Brown /// 10029df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 10039df49d7eSJed Brown /// * `assembled` - Vector to store assembled Operator diagonal 10049df49d7eSJed Brown /// 10059df49d7eSJed Brown /// ``` 10069df49d7eSJed Brown /// # use libceed::prelude::*; 10074d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 10089df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 10099df49d7eSJed Brown /// let ne = 4; 10109df49d7eSJed Brown /// let p = 3; 10119df49d7eSJed Brown /// let q = 4; 10129df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 10139df49d7eSJed Brown /// 10149df49d7eSJed Brown /// // Vectors 1015c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0])?; 1016c68be7a2SJeremy L Thompson /// let mut qdata = ceed.vector(ne * q)?; 10179df49d7eSJed Brown /// qdata.set_value(0.0); 1018c68be7a2SJeremy L Thompson /// let mut u = ceed.vector(ndofs)?; 10199df49d7eSJed Brown /// u.set_value(1.0); 1020c68be7a2SJeremy L Thompson /// let mut v = ceed.vector(ndofs)?; 10219df49d7eSJed Brown /// v.set_value(0.0); 10229df49d7eSJed Brown /// 10239df49d7eSJed Brown /// // Restrictions 10249df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 10259df49d7eSJed Brown /// for i in 0..ne { 10269df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 10279df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 10289df49d7eSJed Brown /// } 1029c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 10309df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 10319df49d7eSJed Brown /// for i in 0..ne { 10329df49d7eSJed Brown /// indu[p * i + 0] = (2 * i) as i32; 10339df49d7eSJed Brown /// indu[p * i + 1] = (2 * i + 1) as i32; 10349df49d7eSJed Brown /// indu[p * i + 2] = (2 * i + 2) as i32; 10359df49d7eSJed Brown /// } 1036c68be7a2SJeremy L Thompson /// let ru = ceed.elem_restriction(ne, p, 1, 1, ndofs, MemType::Host, &indu)?; 10379df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 1038c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 10399df49d7eSJed Brown /// 10409df49d7eSJed Brown /// // Bases 1041c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 1042c68be7a2SJeremy L Thompson /// let bu = ceed.basis_tensor_H1_Lagrange(1, 1, p, q, QuadMode::Gauss)?; 10439df49d7eSJed Brown /// 10449df49d7eSJed Brown /// // Build quadrature data 1045c68be7a2SJeremy L Thompson /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 1046c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 1047c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 1048c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 1049c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)? 1050c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata)?; 10519df49d7eSJed Brown /// 10529df49d7eSJed Brown /// // Mass operator 1053c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 10549df49d7eSJed Brown /// let op_mass = ceed 1055c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 1056c68be7a2SJeremy L Thompson /// .field("u", &ru, &bu, VectorOpt::Active)? 1057c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, &qdata)? 1058c68be7a2SJeremy L Thompson /// .field("v", &ru, &bu, VectorOpt::Active)?; 10599df49d7eSJed Brown /// 10609df49d7eSJed Brown /// // Diagonal 1061c68be7a2SJeremy L Thompson /// let mut diag = ceed.vector(ndofs)?; 10629df49d7eSJed Brown /// diag.set_value(0.0); 1063c68be7a2SJeremy L Thompson /// op_mass.linear_assemble_diagonal(&mut diag)?; 10649df49d7eSJed Brown /// 10659df49d7eSJed Brown /// // Manual diagonal computation 1066c68be7a2SJeremy L Thompson /// let mut true_diag = ceed.vector(ndofs)?; 10679df49d7eSJed Brown /// for i in 0..ndofs { 10689df49d7eSJed Brown /// u.set_value(0.0); 10699df49d7eSJed Brown /// { 1070e78171edSJeremy L Thompson /// let mut u_array = u.view_mut()?; 10719df49d7eSJed Brown /// u_array[i] = 1.; 10729df49d7eSJed Brown /// } 10739df49d7eSJed Brown /// 1074c68be7a2SJeremy L Thompson /// op_mass.apply(&u, &mut v)?; 10759df49d7eSJed Brown /// 10769df49d7eSJed Brown /// { 1077e78171edSJeremy L Thompson /// let v_array = v.view_mut()?; 1078e78171edSJeremy L Thompson /// let mut true_array = true_diag.view_mut()?; 10799df49d7eSJed Brown /// true_array[i] = v_array[i]; 10809df49d7eSJed Brown /// } 10819df49d7eSJed Brown /// } 10829df49d7eSJed Brown /// 10839df49d7eSJed Brown /// // Check 1084e78171edSJeremy L Thompson /// diag.view()? 10859df49d7eSJed Brown /// .iter() 1086e78171edSJeremy L Thompson /// .zip(true_diag.view()?.iter()) 10879df49d7eSJed Brown /// .for_each(|(computed, actual)| { 10889df49d7eSJed Brown /// assert!( 108980a9ef05SNatalie Beams /// (*computed - *actual).abs() < 10.0 * libceed::EPSILON, 10909df49d7eSJed Brown /// "Diagonal entry incorrect" 10919df49d7eSJed Brown /// ); 10929df49d7eSJed Brown /// }); 1093c68be7a2SJeremy L Thompson /// # Ok(()) 1094c68be7a2SJeremy L Thompson /// # } 10959df49d7eSJed Brown /// ``` 10969df49d7eSJed Brown pub fn linear_assemble_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> { 10979df49d7eSJed Brown self.op_core.linear_assemble_diagonal(assembled) 10989df49d7eSJed Brown } 10999df49d7eSJed Brown 11009df49d7eSJed Brown /// Assemble the diagonal of a square linear Operator 11019df49d7eSJed Brown /// 11029df49d7eSJed Brown /// This sums into a Vector with the diagonal of a linear Operator. 11039df49d7eSJed Brown /// 11049df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 11059df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 11069df49d7eSJed Brown /// 11079df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 11089df49d7eSJed Brown /// * `assembled` - Vector to store assembled Operator diagonal 11099df49d7eSJed Brown /// 11109df49d7eSJed Brown /// 11119df49d7eSJed Brown /// ``` 11129df49d7eSJed Brown /// # use libceed::prelude::*; 11134d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 11149df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 11159df49d7eSJed Brown /// let ne = 4; 11169df49d7eSJed Brown /// let p = 3; 11179df49d7eSJed Brown /// let q = 4; 11189df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 11199df49d7eSJed Brown /// 11209df49d7eSJed Brown /// // Vectors 1121c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0])?; 1122c68be7a2SJeremy L Thompson /// let mut qdata = ceed.vector(ne * q)?; 11239df49d7eSJed Brown /// qdata.set_value(0.0); 1124c68be7a2SJeremy L Thompson /// let mut u = ceed.vector(ndofs)?; 11259df49d7eSJed Brown /// u.set_value(1.0); 1126c68be7a2SJeremy L Thompson /// let mut v = ceed.vector(ndofs)?; 11279df49d7eSJed Brown /// v.set_value(0.0); 11289df49d7eSJed Brown /// 11299df49d7eSJed Brown /// // Restrictions 11309df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 11319df49d7eSJed Brown /// for i in 0..ne { 11329df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 11339df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 11349df49d7eSJed Brown /// } 1135c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 11369df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 11379df49d7eSJed Brown /// for i in 0..ne { 11389df49d7eSJed Brown /// indu[p * i + 0] = (2 * i) as i32; 11399df49d7eSJed Brown /// indu[p * i + 1] = (2 * i + 1) as i32; 11409df49d7eSJed Brown /// indu[p * i + 2] = (2 * i + 2) as i32; 11419df49d7eSJed Brown /// } 1142c68be7a2SJeremy L Thompson /// let ru = ceed.elem_restriction(ne, p, 1, 1, ndofs, MemType::Host, &indu)?; 11439df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 1144c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 11459df49d7eSJed Brown /// 11469df49d7eSJed Brown /// // Bases 1147c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 1148c68be7a2SJeremy L Thompson /// let bu = ceed.basis_tensor_H1_Lagrange(1, 1, p, q, QuadMode::Gauss)?; 11499df49d7eSJed Brown /// 11509df49d7eSJed Brown /// // Build quadrature data 1151c68be7a2SJeremy L Thompson /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 1152c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 1153c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 1154c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 1155c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)? 1156c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata)?; 11579df49d7eSJed Brown /// 11589df49d7eSJed Brown /// // Mass operator 1159c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 11609df49d7eSJed Brown /// let op_mass = ceed 1161c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 1162c68be7a2SJeremy L Thompson /// .field("u", &ru, &bu, VectorOpt::Active)? 1163c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, &qdata)? 1164c68be7a2SJeremy L Thompson /// .field("v", &ru, &bu, VectorOpt::Active)?; 11659df49d7eSJed Brown /// 11669df49d7eSJed Brown /// // Diagonal 1167c68be7a2SJeremy L Thompson /// let mut diag = ceed.vector(ndofs)?; 11689df49d7eSJed Brown /// diag.set_value(1.0); 1169c68be7a2SJeremy L Thompson /// op_mass.linear_assemble_add_diagonal(&mut diag)?; 11709df49d7eSJed Brown /// 11719df49d7eSJed Brown /// // Manual diagonal computation 1172c68be7a2SJeremy L Thompson /// let mut true_diag = ceed.vector(ndofs)?; 11739df49d7eSJed Brown /// for i in 0..ndofs { 11749df49d7eSJed Brown /// u.set_value(0.0); 11759df49d7eSJed Brown /// { 1176e78171edSJeremy L Thompson /// let mut u_array = u.view_mut()?; 11779df49d7eSJed Brown /// u_array[i] = 1.; 11789df49d7eSJed Brown /// } 11799df49d7eSJed Brown /// 1180c68be7a2SJeremy L Thompson /// op_mass.apply(&u, &mut v)?; 11819df49d7eSJed Brown /// 11829df49d7eSJed Brown /// { 1183e78171edSJeremy L Thompson /// let v_array = v.view_mut()?; 1184e78171edSJeremy L Thompson /// let mut true_array = true_diag.view_mut()?; 11859df49d7eSJed Brown /// true_array[i] = v_array[i] + 1.0; 11869df49d7eSJed Brown /// } 11879df49d7eSJed Brown /// } 11889df49d7eSJed Brown /// 11899df49d7eSJed Brown /// // Check 1190e78171edSJeremy L Thompson /// diag.view()? 11919df49d7eSJed Brown /// .iter() 1192e78171edSJeremy L Thompson /// .zip(true_diag.view()?.iter()) 11939df49d7eSJed Brown /// .for_each(|(computed, actual)| { 11949df49d7eSJed Brown /// assert!( 119580a9ef05SNatalie Beams /// (*computed - *actual).abs() < 10.0 * libceed::EPSILON, 11969df49d7eSJed Brown /// "Diagonal entry incorrect" 11979df49d7eSJed Brown /// ); 11989df49d7eSJed Brown /// }); 1199c68be7a2SJeremy L Thompson /// # Ok(()) 1200c68be7a2SJeremy L Thompson /// # } 12019df49d7eSJed Brown /// ``` 12029df49d7eSJed Brown pub fn linear_assemble_add_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> { 12039df49d7eSJed Brown self.op_core.linear_assemble_add_diagonal(assembled) 12049df49d7eSJed Brown } 12059df49d7eSJed Brown 12069df49d7eSJed Brown /// Assemble the point block diagonal of a square linear Operator 12079df49d7eSJed Brown /// 12089df49d7eSJed Brown /// This overwrites a Vector with the point block diagonal of a linear 12099df49d7eSJed Brown /// Operator. 12109df49d7eSJed Brown /// 12119df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 12129df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 12139df49d7eSJed Brown /// 12149df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 12159df49d7eSJed Brown /// * `assembled` - Vector to store assembled CeedOperator point block 12169df49d7eSJed Brown /// diagonal, provided in row-major form with an 12179df49d7eSJed Brown /// `ncomp * ncomp` block at each node. The dimensions of 12189df49d7eSJed Brown /// this vector are derived from the active vector for 12199df49d7eSJed Brown /// the CeedOperator. The array has shape 12209df49d7eSJed Brown /// `[nodes, component out, component in]`. 12219df49d7eSJed Brown /// 12229df49d7eSJed Brown /// ``` 12239df49d7eSJed Brown /// # use libceed::prelude::*; 12244d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 12259df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 12269df49d7eSJed Brown /// let ne = 4; 12279df49d7eSJed Brown /// let p = 3; 12289df49d7eSJed Brown /// let q = 4; 12299df49d7eSJed Brown /// let ncomp = 2; 12309df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 12319df49d7eSJed Brown /// 12329df49d7eSJed Brown /// // Vectors 1233c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0])?; 1234c68be7a2SJeremy L Thompson /// let mut qdata = ceed.vector(ne * q)?; 12359df49d7eSJed Brown /// qdata.set_value(0.0); 1236c68be7a2SJeremy L Thompson /// let mut u = ceed.vector(ncomp * ndofs)?; 12379df49d7eSJed Brown /// u.set_value(1.0); 1238c68be7a2SJeremy L Thompson /// let mut v = ceed.vector(ncomp * ndofs)?; 12399df49d7eSJed Brown /// v.set_value(0.0); 12409df49d7eSJed Brown /// 12419df49d7eSJed Brown /// // Restrictions 12429df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 12439df49d7eSJed Brown /// for i in 0..ne { 12449df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 12459df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 12469df49d7eSJed Brown /// } 1247c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 12489df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 12499df49d7eSJed Brown /// for i in 0..ne { 12509df49d7eSJed Brown /// indu[p * i + 0] = (2 * i) as i32; 12519df49d7eSJed Brown /// indu[p * i + 1] = (2 * i + 1) as i32; 12529df49d7eSJed Brown /// indu[p * i + 2] = (2 * i + 2) as i32; 12539df49d7eSJed Brown /// } 1254c68be7a2SJeremy L Thompson /// let ru = ceed.elem_restriction(ne, p, ncomp, ndofs, ncomp * ndofs, MemType::Host, &indu)?; 12559df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 1256c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 12579df49d7eSJed Brown /// 12589df49d7eSJed Brown /// // Bases 1259c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 1260c68be7a2SJeremy L Thompson /// let bu = ceed.basis_tensor_H1_Lagrange(1, ncomp, p, q, QuadMode::Gauss)?; 12619df49d7eSJed Brown /// 12629df49d7eSJed Brown /// // Build quadrature data 1263c68be7a2SJeremy L Thompson /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 1264c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 1265c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 1266c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 1267c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)? 1268c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata)?; 12699df49d7eSJed Brown /// 12709df49d7eSJed Brown /// // Mass operator 12719df49d7eSJed Brown /// let mut mass_2_comp = |[u, qdata, ..]: QFunctionInputs, [v, ..]: QFunctionOutputs| { 12729df49d7eSJed Brown /// // Number of quadrature points 12739df49d7eSJed Brown /// let q = qdata.len(); 12749df49d7eSJed Brown /// 12759df49d7eSJed Brown /// // Iterate over quadrature points 12769df49d7eSJed Brown /// for i in 0..q { 12779df49d7eSJed Brown /// v[i + 0 * q] = u[i + 1 * q] * qdata[i]; 12789df49d7eSJed Brown /// v[i + 1 * q] = u[i + 0 * q] * qdata[i]; 12799df49d7eSJed Brown /// } 12809df49d7eSJed Brown /// 12819df49d7eSJed Brown /// // Return clean error code 12829df49d7eSJed Brown /// 0 12839df49d7eSJed Brown /// }; 12849df49d7eSJed Brown /// 12859df49d7eSJed Brown /// let qf_mass = ceed 1286c68be7a2SJeremy L Thompson /// .q_function_interior(1, Box::new(mass_2_comp))? 1287c68be7a2SJeremy L Thompson /// .input("u", 2, EvalMode::Interp)? 1288c68be7a2SJeremy L Thompson /// .input("qdata", 1, EvalMode::None)? 1289c68be7a2SJeremy L Thompson /// .output("v", 2, EvalMode::Interp)?; 12909df49d7eSJed Brown /// 12919df49d7eSJed Brown /// let op_mass = ceed 1292c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 1293c68be7a2SJeremy L Thompson /// .field("u", &ru, &bu, VectorOpt::Active)? 1294c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, &qdata)? 1295c68be7a2SJeremy L Thompson /// .field("v", &ru, &bu, VectorOpt::Active)?; 12969df49d7eSJed Brown /// 12979df49d7eSJed Brown /// // Diagonal 1298c68be7a2SJeremy L Thompson /// let mut diag = ceed.vector(ncomp * ncomp * ndofs)?; 12999df49d7eSJed Brown /// diag.set_value(0.0); 1300c68be7a2SJeremy L Thompson /// op_mass.linear_assemble_point_block_diagonal(&mut diag)?; 13019df49d7eSJed Brown /// 13029df49d7eSJed Brown /// // Manual diagonal computation 1303c68be7a2SJeremy L Thompson /// let mut true_diag = ceed.vector(ncomp * ncomp * ndofs)?; 13049df49d7eSJed Brown /// for i in 0..ndofs { 13059df49d7eSJed Brown /// for j in 0..ncomp { 13069df49d7eSJed Brown /// u.set_value(0.0); 13079df49d7eSJed Brown /// { 1308e78171edSJeremy L Thompson /// let mut u_array = u.view_mut()?; 13099df49d7eSJed Brown /// u_array[i + j * ndofs] = 1.; 13109df49d7eSJed Brown /// } 13119df49d7eSJed Brown /// 1312c68be7a2SJeremy L Thompson /// op_mass.apply(&u, &mut v)?; 13139df49d7eSJed Brown /// 13149df49d7eSJed Brown /// { 1315e78171edSJeremy L Thompson /// let v_array = v.view_mut()?; 1316e78171edSJeremy L Thompson /// let mut true_array = true_diag.view_mut()?; 13179df49d7eSJed Brown /// for k in 0..ncomp { 13189df49d7eSJed Brown /// true_array[i * ncomp * ncomp + k * ncomp + j] = v_array[i + k * ndofs]; 13199df49d7eSJed Brown /// } 13209df49d7eSJed Brown /// } 13219df49d7eSJed Brown /// } 13229df49d7eSJed Brown /// } 13239df49d7eSJed Brown /// 13249df49d7eSJed Brown /// // Check 1325e78171edSJeremy L Thompson /// diag.view()? 13269df49d7eSJed Brown /// .iter() 1327e78171edSJeremy L Thompson /// .zip(true_diag.view()?.iter()) 13289df49d7eSJed Brown /// .for_each(|(computed, actual)| { 13299df49d7eSJed Brown /// assert!( 133080a9ef05SNatalie Beams /// (*computed - *actual).abs() < 10.0 * libceed::EPSILON, 13319df49d7eSJed Brown /// "Diagonal entry incorrect" 13329df49d7eSJed Brown /// ); 13339df49d7eSJed Brown /// }); 1334c68be7a2SJeremy L Thompson /// # Ok(()) 1335c68be7a2SJeremy L Thompson /// # } 13369df49d7eSJed Brown /// ``` 13379df49d7eSJed Brown pub fn linear_assemble_point_block_diagonal( 13389df49d7eSJed Brown &self, 13399df49d7eSJed Brown assembled: &mut Vector, 13409df49d7eSJed Brown ) -> crate::Result<i32> { 13419df49d7eSJed Brown self.op_core.linear_assemble_point_block_diagonal(assembled) 13429df49d7eSJed Brown } 13439df49d7eSJed Brown 13449df49d7eSJed Brown /// Assemble the point block diagonal of a square linear Operator 13459df49d7eSJed Brown /// 13469df49d7eSJed Brown /// This sums into a Vector with the point block diagonal of a linear 13479df49d7eSJed Brown /// Operator. 13489df49d7eSJed Brown /// 13499df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 13509df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 13519df49d7eSJed Brown /// 13529df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 13539df49d7eSJed Brown /// * `assembled` - Vector to store assembled CeedOperator point block 13549df49d7eSJed Brown /// diagonal, provided in row-major form with an 13559df49d7eSJed Brown /// `ncomp * ncomp` block at each node. The dimensions of 13569df49d7eSJed Brown /// this vector are derived from the active vector for 13579df49d7eSJed Brown /// the CeedOperator. The array has shape 13589df49d7eSJed Brown /// `[nodes, component out, component in]`. 13599df49d7eSJed Brown /// 13609df49d7eSJed Brown /// ``` 13619df49d7eSJed Brown /// # use libceed::prelude::*; 13624d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 13639df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 13649df49d7eSJed Brown /// let ne = 4; 13659df49d7eSJed Brown /// let p = 3; 13669df49d7eSJed Brown /// let q = 4; 13679df49d7eSJed Brown /// let ncomp = 2; 13689df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 13699df49d7eSJed Brown /// 13709df49d7eSJed Brown /// // Vectors 1371c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0])?; 1372c68be7a2SJeremy L Thompson /// let mut qdata = ceed.vector(ne * q)?; 13739df49d7eSJed Brown /// qdata.set_value(0.0); 1374c68be7a2SJeremy L Thompson /// let mut u = ceed.vector(ncomp * ndofs)?; 13759df49d7eSJed Brown /// u.set_value(1.0); 1376c68be7a2SJeremy L Thompson /// let mut v = ceed.vector(ncomp * ndofs)?; 13779df49d7eSJed Brown /// v.set_value(0.0); 13789df49d7eSJed Brown /// 13799df49d7eSJed Brown /// // Restrictions 13809df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 13819df49d7eSJed Brown /// for i in 0..ne { 13829df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 13839df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 13849df49d7eSJed Brown /// } 1385c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 13869df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 13879df49d7eSJed Brown /// for i in 0..ne { 13889df49d7eSJed Brown /// indu[p * i + 0] = (2 * i) as i32; 13899df49d7eSJed Brown /// indu[p * i + 1] = (2 * i + 1) as i32; 13909df49d7eSJed Brown /// indu[p * i + 2] = (2 * i + 2) as i32; 13919df49d7eSJed Brown /// } 1392c68be7a2SJeremy L Thompson /// let ru = ceed.elem_restriction(ne, p, ncomp, ndofs, ncomp * ndofs, MemType::Host, &indu)?; 13939df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 1394c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 13959df49d7eSJed Brown /// 13969df49d7eSJed Brown /// // Bases 1397c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 1398c68be7a2SJeremy L Thompson /// let bu = ceed.basis_tensor_H1_Lagrange(1, ncomp, p, q, QuadMode::Gauss)?; 13999df49d7eSJed Brown /// 14009df49d7eSJed Brown /// // Build quadrature data 1401c68be7a2SJeremy L Thompson /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 1402c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 1403c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 1404c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 1405c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)? 1406c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata)?; 14079df49d7eSJed Brown /// 14089df49d7eSJed Brown /// // Mass operator 14099df49d7eSJed Brown /// let mut mass_2_comp = |[u, qdata, ..]: QFunctionInputs, [v, ..]: QFunctionOutputs| { 14109df49d7eSJed Brown /// // Number of quadrature points 14119df49d7eSJed Brown /// let q = qdata.len(); 14129df49d7eSJed Brown /// 14139df49d7eSJed Brown /// // Iterate over quadrature points 14149df49d7eSJed Brown /// for i in 0..q { 14159df49d7eSJed Brown /// v[i + 0 * q] = u[i + 1 * q] * qdata[i]; 14169df49d7eSJed Brown /// v[i + 1 * q] = u[i + 0 * q] * qdata[i]; 14179df49d7eSJed Brown /// } 14189df49d7eSJed Brown /// 14199df49d7eSJed Brown /// // Return clean error code 14209df49d7eSJed Brown /// 0 14219df49d7eSJed Brown /// }; 14229df49d7eSJed Brown /// 14239df49d7eSJed Brown /// let qf_mass = ceed 1424c68be7a2SJeremy L Thompson /// .q_function_interior(1, Box::new(mass_2_comp))? 1425c68be7a2SJeremy L Thompson /// .input("u", 2, EvalMode::Interp)? 1426c68be7a2SJeremy L Thompson /// .input("qdata", 1, EvalMode::None)? 1427c68be7a2SJeremy L Thompson /// .output("v", 2, EvalMode::Interp)?; 14289df49d7eSJed Brown /// 14299df49d7eSJed Brown /// let op_mass = ceed 1430c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 1431c68be7a2SJeremy L Thompson /// .field("u", &ru, &bu, VectorOpt::Active)? 1432c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, &qdata)? 1433c68be7a2SJeremy L Thompson /// .field("v", &ru, &bu, VectorOpt::Active)?; 14349df49d7eSJed Brown /// 14359df49d7eSJed Brown /// // Diagonal 1436c68be7a2SJeremy L Thompson /// let mut diag = ceed.vector(ncomp * ncomp * ndofs)?; 14379df49d7eSJed Brown /// diag.set_value(1.0); 1438c68be7a2SJeremy L Thompson /// op_mass.linear_assemble_add_point_block_diagonal(&mut diag)?; 14399df49d7eSJed Brown /// 14409df49d7eSJed Brown /// // Manual diagonal computation 1441c68be7a2SJeremy L Thompson /// let mut true_diag = ceed.vector(ncomp * ncomp * ndofs)?; 14429df49d7eSJed Brown /// for i in 0..ndofs { 14439df49d7eSJed Brown /// for j in 0..ncomp { 14449df49d7eSJed Brown /// u.set_value(0.0); 14459df49d7eSJed Brown /// { 1446e78171edSJeremy L Thompson /// let mut u_array = u.view_mut()?; 14479df49d7eSJed Brown /// u_array[i + j * ndofs] = 1.; 14489df49d7eSJed Brown /// } 14499df49d7eSJed Brown /// 1450c68be7a2SJeremy L Thompson /// op_mass.apply(&u, &mut v)?; 14519df49d7eSJed Brown /// 14529df49d7eSJed Brown /// { 1453e78171edSJeremy L Thompson /// let v_array = v.view_mut()?; 1454e78171edSJeremy L Thompson /// let mut true_array = true_diag.view_mut()?; 14559df49d7eSJed Brown /// for k in 0..ncomp { 14569df49d7eSJed Brown /// true_array[i * ncomp * ncomp + k * ncomp + j] = v_array[i + k * ndofs]; 14579df49d7eSJed Brown /// } 14589df49d7eSJed Brown /// } 14599df49d7eSJed Brown /// } 14609df49d7eSJed Brown /// } 14619df49d7eSJed Brown /// 14629df49d7eSJed Brown /// // Check 1463e78171edSJeremy L Thompson /// diag.view()? 14649df49d7eSJed Brown /// .iter() 1465e78171edSJeremy L Thompson /// .zip(true_diag.view()?.iter()) 14669df49d7eSJed Brown /// .for_each(|(computed, actual)| { 14679df49d7eSJed Brown /// assert!( 146880a9ef05SNatalie Beams /// (*computed - 1.0 - *actual).abs() < 10.0 * libceed::EPSILON, 14699df49d7eSJed Brown /// "Diagonal entry incorrect" 14709df49d7eSJed Brown /// ); 14719df49d7eSJed Brown /// }); 1472c68be7a2SJeremy L Thompson /// # Ok(()) 1473c68be7a2SJeremy L Thompson /// # } 14749df49d7eSJed Brown /// ``` 14759df49d7eSJed Brown pub fn linear_assemble_add_point_block_diagonal( 14769df49d7eSJed Brown &self, 14779df49d7eSJed Brown assembled: &mut Vector, 14789df49d7eSJed Brown ) -> crate::Result<i32> { 14799df49d7eSJed Brown self.op_core 14809df49d7eSJed Brown .linear_assemble_add_point_block_diagonal(assembled) 14819df49d7eSJed Brown } 14829df49d7eSJed Brown 14839df49d7eSJed Brown /// Create a multigrid coarse Operator and level transfer Operators for a 14849df49d7eSJed Brown /// given Operator, creating the prolongation basis from the fine and 14859df49d7eSJed Brown /// coarse grid interpolation 14869df49d7eSJed Brown /// 14879df49d7eSJed Brown /// * `p_mult_fine` - Lvector multiplicity in parallel gather/scatter 14889df49d7eSJed Brown /// * `rstr_coarse` - Coarse grid restriction 14899df49d7eSJed Brown /// * `basis_coarse` - Coarse grid active vector basis 14909df49d7eSJed Brown /// 14919df49d7eSJed Brown /// ``` 14929df49d7eSJed Brown /// # use libceed::prelude::*; 14934d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 14949df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 14959df49d7eSJed Brown /// let ne = 15; 14969df49d7eSJed Brown /// let p_coarse = 3; 14979df49d7eSJed Brown /// let p_fine = 5; 14989df49d7eSJed Brown /// let q = 6; 14999df49d7eSJed Brown /// let ndofs_coarse = p_coarse * ne - ne + 1; 15009df49d7eSJed Brown /// let ndofs_fine = p_fine * ne - ne + 1; 15019df49d7eSJed Brown /// 15029df49d7eSJed Brown /// // Vectors 15039df49d7eSJed Brown /// let x_array = (0..ne + 1) 150480a9ef05SNatalie Beams /// .map(|i| 2.0 * i as Scalar / ne as Scalar - 1.0) 150580a9ef05SNatalie Beams /// .collect::<Vec<Scalar>>(); 1506c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&x_array)?; 1507c68be7a2SJeremy L Thompson /// let mut qdata = ceed.vector(ne * q)?; 15089df49d7eSJed Brown /// qdata.set_value(0.0); 1509c68be7a2SJeremy L Thompson /// let mut u_coarse = ceed.vector(ndofs_coarse)?; 15109df49d7eSJed Brown /// u_coarse.set_value(1.0); 1511c68be7a2SJeremy L Thompson /// let mut u_fine = ceed.vector(ndofs_fine)?; 15129df49d7eSJed Brown /// u_fine.set_value(1.0); 1513c68be7a2SJeremy L Thompson /// let mut v_coarse = ceed.vector(ndofs_coarse)?; 15149df49d7eSJed Brown /// v_coarse.set_value(0.0); 1515c68be7a2SJeremy L Thompson /// let mut v_fine = ceed.vector(ndofs_fine)?; 15169df49d7eSJed Brown /// v_fine.set_value(0.0); 1517c68be7a2SJeremy L Thompson /// let mut multiplicity = ceed.vector(ndofs_fine)?; 15189df49d7eSJed Brown /// multiplicity.set_value(1.0); 15199df49d7eSJed Brown /// 15209df49d7eSJed Brown /// // Restrictions 15219df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 1522c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 15239df49d7eSJed Brown /// 15249df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 15259df49d7eSJed Brown /// for i in 0..ne { 15269df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 15279df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 15289df49d7eSJed Brown /// } 1529c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 15309df49d7eSJed Brown /// 15319df49d7eSJed Brown /// let mut indu_coarse: Vec<i32> = vec![0; p_coarse * ne]; 15329df49d7eSJed Brown /// for i in 0..ne { 15339df49d7eSJed Brown /// for j in 0..p_coarse { 15349df49d7eSJed Brown /// indu_coarse[p_coarse * i + j] = (i + j) as i32; 15359df49d7eSJed Brown /// } 15369df49d7eSJed Brown /// } 1537c68be7a2SJeremy L Thompson /// let ru_coarse = ceed.elem_restriction( 15389df49d7eSJed Brown /// ne, 15399df49d7eSJed Brown /// p_coarse, 15409df49d7eSJed Brown /// 1, 15419df49d7eSJed Brown /// 1, 15429df49d7eSJed Brown /// ndofs_coarse, 15439df49d7eSJed Brown /// MemType::Host, 15449df49d7eSJed Brown /// &indu_coarse, 1545c68be7a2SJeremy L Thompson /// )?; 15469df49d7eSJed Brown /// 15479df49d7eSJed Brown /// let mut indu_fine: Vec<i32> = vec![0; p_fine * ne]; 15489df49d7eSJed Brown /// for i in 0..ne { 15499df49d7eSJed Brown /// for j in 0..p_fine { 15509df49d7eSJed Brown /// indu_fine[p_fine * i + j] = (i + j) as i32; 15519df49d7eSJed Brown /// } 15529df49d7eSJed Brown /// } 1553c68be7a2SJeremy L Thompson /// let ru_fine = ceed.elem_restriction(ne, p_fine, 1, 1, ndofs_fine, MemType::Host, &indu_fine)?; 15549df49d7eSJed Brown /// 15559df49d7eSJed Brown /// // Bases 1556c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 1557c68be7a2SJeremy L Thompson /// let bu_coarse = ceed.basis_tensor_H1_Lagrange(1, 1, p_coarse, q, QuadMode::Gauss)?; 1558c68be7a2SJeremy L Thompson /// let bu_fine = ceed.basis_tensor_H1_Lagrange(1, 1, p_fine, q, QuadMode::Gauss)?; 15599df49d7eSJed Brown /// 15609df49d7eSJed Brown /// // Build quadrature data 1561c68be7a2SJeremy L Thompson /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 1562c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 1563c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 1564c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 1565c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)? 1566c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata)?; 15679df49d7eSJed Brown /// 15689df49d7eSJed Brown /// // Mass operator 1569c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 15709df49d7eSJed Brown /// let op_mass_fine = ceed 1571c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 1572c68be7a2SJeremy L Thompson /// .field("u", &ru_fine, &bu_fine, VectorOpt::Active)? 1573c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, &qdata)? 1574c68be7a2SJeremy L Thompson /// .field("v", &ru_fine, &bu_fine, VectorOpt::Active)?; 15759df49d7eSJed Brown /// 15769df49d7eSJed Brown /// // Multigrid setup 1577c68be7a2SJeremy L Thompson /// let (op_mass_coarse, op_prolong, op_restrict) = 1578c68be7a2SJeremy L Thompson /// op_mass_fine.create_multigrid_level(&multiplicity, &ru_coarse, &bu_coarse)?; 15799df49d7eSJed Brown /// 15809df49d7eSJed Brown /// // Coarse problem 15819df49d7eSJed Brown /// u_coarse.set_value(1.0); 1582c68be7a2SJeremy L Thompson /// op_mass_coarse.apply(&u_coarse, &mut v_coarse)?; 15839df49d7eSJed Brown /// 15849df49d7eSJed Brown /// // Check 1585e78171edSJeremy L Thompson /// let sum: Scalar = v_coarse.view()?.iter().sum(); 15869df49d7eSJed Brown /// assert!( 158780a9ef05SNatalie Beams /// (sum - 2.0).abs() < 50.0 * libceed::EPSILON, 15889df49d7eSJed Brown /// "Incorrect interval length computed" 15899df49d7eSJed Brown /// ); 15909df49d7eSJed Brown /// 15919df49d7eSJed Brown /// // Prolong 1592c68be7a2SJeremy L Thompson /// op_prolong.apply(&u_coarse, &mut u_fine)?; 15939df49d7eSJed Brown /// 15949df49d7eSJed Brown /// // Fine problem 1595c68be7a2SJeremy L Thompson /// op_mass_fine.apply(&u_fine, &mut v_fine)?; 15969df49d7eSJed Brown /// 15979df49d7eSJed Brown /// // Check 1598e78171edSJeremy L Thompson /// let sum: Scalar = v_fine.view()?.iter().sum(); 15999df49d7eSJed Brown /// assert!( 160080a9ef05SNatalie Beams /// (sum - 2.0).abs() < 50.0 * libceed::EPSILON, 16019df49d7eSJed Brown /// "Incorrect interval length computed" 16029df49d7eSJed Brown /// ); 16039df49d7eSJed Brown /// 16049df49d7eSJed Brown /// // Restrict 1605c68be7a2SJeremy L Thompson /// op_restrict.apply(&v_fine, &mut v_coarse)?; 16069df49d7eSJed Brown /// 16079df49d7eSJed Brown /// // Check 1608e78171edSJeremy L Thompson /// let sum: Scalar = v_coarse.view()?.iter().sum(); 16099df49d7eSJed Brown /// assert!( 161080a9ef05SNatalie Beams /// (sum - 2.0).abs() < 50.0 * libceed::EPSILON, 16119df49d7eSJed Brown /// "Incorrect interval length computed" 16129df49d7eSJed Brown /// ); 1613c68be7a2SJeremy L Thompson /// # Ok(()) 1614c68be7a2SJeremy L Thompson /// # } 16159df49d7eSJed Brown /// ``` 16169df49d7eSJed Brown pub fn create_multigrid_level( 16179df49d7eSJed Brown &self, 16189df49d7eSJed Brown p_mult_fine: &Vector, 16199df49d7eSJed Brown rstr_coarse: &ElemRestriction, 16209df49d7eSJed Brown basis_coarse: &Basis, 16219df49d7eSJed Brown ) -> crate::Result<(Operator, Operator, Operator)> { 16229df49d7eSJed Brown let mut ptr_coarse = std::ptr::null_mut(); 16239df49d7eSJed Brown let mut ptr_prolong = std::ptr::null_mut(); 16249df49d7eSJed Brown let mut ptr_restrict = std::ptr::null_mut(); 16259df49d7eSJed Brown let ierr = unsafe { 16269df49d7eSJed Brown bind_ceed::CeedOperatorMultigridLevelCreate( 16279df49d7eSJed Brown self.op_core.ptr, 16289df49d7eSJed Brown p_mult_fine.ptr, 16299df49d7eSJed Brown rstr_coarse.ptr, 16309df49d7eSJed Brown basis_coarse.ptr, 16319df49d7eSJed Brown &mut ptr_coarse, 16329df49d7eSJed Brown &mut ptr_prolong, 16339df49d7eSJed Brown &mut ptr_restrict, 16349df49d7eSJed Brown ) 16359df49d7eSJed Brown }; 16361142270cSJeremy L Thompson self.op_core.check_error(ierr)?; 16371142270cSJeremy L Thompson let op_coarse = Operator::from_raw(ptr_coarse)?; 16381142270cSJeremy L Thompson let op_prolong = Operator::from_raw(ptr_prolong)?; 16391142270cSJeremy L Thompson let op_restrict = Operator::from_raw(ptr_restrict)?; 16409df49d7eSJed Brown Ok((op_coarse, op_prolong, op_restrict)) 16419df49d7eSJed Brown } 16429df49d7eSJed Brown 16439df49d7eSJed Brown /// Create a multigrid coarse Operator and level transfer Operators for a 16449df49d7eSJed Brown /// given Operator with a tensor basis for the active basis 16459df49d7eSJed Brown /// 16469df49d7eSJed Brown /// * `p_mult_fine` - Lvector multiplicity in parallel gather/scatter 16479df49d7eSJed Brown /// * `rstr_coarse` - Coarse grid restriction 16489df49d7eSJed Brown /// * `basis_coarse` - Coarse grid active vector basis 16499df49d7eSJed Brown /// * `interp_c_to_f` - Matrix for coarse to fine 16509df49d7eSJed Brown /// 16519df49d7eSJed Brown /// ``` 16529df49d7eSJed Brown /// # use libceed::prelude::*; 16534d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 16549df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 16559df49d7eSJed Brown /// let ne = 15; 16569df49d7eSJed Brown /// let p_coarse = 3; 16579df49d7eSJed Brown /// let p_fine = 5; 16589df49d7eSJed Brown /// let q = 6; 16599df49d7eSJed Brown /// let ndofs_coarse = p_coarse * ne - ne + 1; 16609df49d7eSJed Brown /// let ndofs_fine = p_fine * ne - ne + 1; 16619df49d7eSJed Brown /// 16629df49d7eSJed Brown /// // Vectors 16639df49d7eSJed Brown /// let x_array = (0..ne + 1) 166480a9ef05SNatalie Beams /// .map(|i| 2.0 * i as Scalar / ne as Scalar - 1.0) 166580a9ef05SNatalie Beams /// .collect::<Vec<Scalar>>(); 1666c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&x_array)?; 1667c68be7a2SJeremy L Thompson /// let mut qdata = ceed.vector(ne * q)?; 16689df49d7eSJed Brown /// qdata.set_value(0.0); 1669c68be7a2SJeremy L Thompson /// let mut u_coarse = ceed.vector(ndofs_coarse)?; 16709df49d7eSJed Brown /// u_coarse.set_value(1.0); 1671c68be7a2SJeremy L Thompson /// let mut u_fine = ceed.vector(ndofs_fine)?; 16729df49d7eSJed Brown /// u_fine.set_value(1.0); 1673c68be7a2SJeremy L Thompson /// let mut v_coarse = ceed.vector(ndofs_coarse)?; 16749df49d7eSJed Brown /// v_coarse.set_value(0.0); 1675c68be7a2SJeremy L Thompson /// let mut v_fine = ceed.vector(ndofs_fine)?; 16769df49d7eSJed Brown /// v_fine.set_value(0.0); 1677c68be7a2SJeremy L Thompson /// let mut multiplicity = ceed.vector(ndofs_fine)?; 16789df49d7eSJed Brown /// multiplicity.set_value(1.0); 16799df49d7eSJed Brown /// 16809df49d7eSJed Brown /// // Restrictions 16819df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 1682c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 16839df49d7eSJed Brown /// 16849df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 16859df49d7eSJed Brown /// for i in 0..ne { 16869df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 16879df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 16889df49d7eSJed Brown /// } 1689c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 16909df49d7eSJed Brown /// 16919df49d7eSJed Brown /// let mut indu_coarse: Vec<i32> = vec![0; p_coarse * ne]; 16929df49d7eSJed Brown /// for i in 0..ne { 16939df49d7eSJed Brown /// for j in 0..p_coarse { 16949df49d7eSJed Brown /// indu_coarse[p_coarse * i + j] = (i + j) as i32; 16959df49d7eSJed Brown /// } 16969df49d7eSJed Brown /// } 1697c68be7a2SJeremy L Thompson /// let ru_coarse = ceed.elem_restriction( 16989df49d7eSJed Brown /// ne, 16999df49d7eSJed Brown /// p_coarse, 17009df49d7eSJed Brown /// 1, 17019df49d7eSJed Brown /// 1, 17029df49d7eSJed Brown /// ndofs_coarse, 17039df49d7eSJed Brown /// MemType::Host, 17049df49d7eSJed Brown /// &indu_coarse, 1705c68be7a2SJeremy L Thompson /// )?; 17069df49d7eSJed Brown /// 17079df49d7eSJed Brown /// let mut indu_fine: Vec<i32> = vec![0; p_fine * ne]; 17089df49d7eSJed Brown /// for i in 0..ne { 17099df49d7eSJed Brown /// for j in 0..p_fine { 17109df49d7eSJed Brown /// indu_fine[p_fine * i + j] = (i + j) as i32; 17119df49d7eSJed Brown /// } 17129df49d7eSJed Brown /// } 1713c68be7a2SJeremy L Thompson /// let ru_fine = ceed.elem_restriction(ne, p_fine, 1, 1, ndofs_fine, MemType::Host, &indu_fine)?; 17149df49d7eSJed Brown /// 17159df49d7eSJed Brown /// // Bases 1716c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 1717c68be7a2SJeremy L Thompson /// let bu_coarse = ceed.basis_tensor_H1_Lagrange(1, 1, p_coarse, q, QuadMode::Gauss)?; 1718c68be7a2SJeremy L Thompson /// let bu_fine = ceed.basis_tensor_H1_Lagrange(1, 1, p_fine, q, QuadMode::Gauss)?; 17199df49d7eSJed Brown /// 17209df49d7eSJed Brown /// // Build quadrature data 1721c68be7a2SJeremy L Thompson /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 1722c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 1723c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 1724c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 1725c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)? 1726c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata)?; 17279df49d7eSJed Brown /// 17289df49d7eSJed Brown /// // Mass operator 1729c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 17309df49d7eSJed Brown /// let op_mass_fine = ceed 1731c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 1732c68be7a2SJeremy L Thompson /// .field("u", &ru_fine, &bu_fine, VectorOpt::Active)? 1733c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, &qdata)? 1734c68be7a2SJeremy L Thompson /// .field("v", &ru_fine, &bu_fine, VectorOpt::Active)?; 17359df49d7eSJed Brown /// 17369df49d7eSJed Brown /// // Multigrid setup 173780a9ef05SNatalie Beams /// let mut interp_c_to_f: Vec<Scalar> = vec![0.; p_coarse * p_fine]; 17389df49d7eSJed Brown /// { 1739c68be7a2SJeremy L Thompson /// let mut coarse = ceed.vector(p_coarse)?; 1740c68be7a2SJeremy L Thompson /// let mut fine = ceed.vector(p_fine)?; 1741c68be7a2SJeremy L Thompson /// let basis_c_to_f = 1742c68be7a2SJeremy L Thompson /// ceed.basis_tensor_H1_Lagrange(1, 1, p_coarse, p_fine, QuadMode::GaussLobatto)?; 17439df49d7eSJed Brown /// for i in 0..p_coarse { 17449df49d7eSJed Brown /// coarse.set_value(0.0); 17459df49d7eSJed Brown /// { 1746e78171edSJeremy L Thompson /// let mut array = coarse.view_mut()?; 17479df49d7eSJed Brown /// array[i] = 1.; 17489df49d7eSJed Brown /// } 1749c68be7a2SJeremy L Thompson /// basis_c_to_f.apply( 17509df49d7eSJed Brown /// 1, 17519df49d7eSJed Brown /// TransposeMode::NoTranspose, 17529df49d7eSJed Brown /// EvalMode::Interp, 17539df49d7eSJed Brown /// &coarse, 17549df49d7eSJed Brown /// &mut fine, 1755c68be7a2SJeremy L Thompson /// )?; 1756e78171edSJeremy L Thompson /// let array = fine.view()?; 17579df49d7eSJed Brown /// for j in 0..p_fine { 17589df49d7eSJed Brown /// interp_c_to_f[j * p_coarse + i] = array[j]; 17599df49d7eSJed Brown /// } 17609df49d7eSJed Brown /// } 17619df49d7eSJed Brown /// } 1762c68be7a2SJeremy L Thompson /// let (op_mass_coarse, op_prolong, op_restrict) = op_mass_fine.create_multigrid_level_tensor_H1( 1763c68be7a2SJeremy L Thompson /// &multiplicity, 1764c68be7a2SJeremy L Thompson /// &ru_coarse, 1765c68be7a2SJeremy L Thompson /// &bu_coarse, 1766c68be7a2SJeremy L Thompson /// &interp_c_to_f, 1767c68be7a2SJeremy L Thompson /// )?; 17689df49d7eSJed Brown /// 17699df49d7eSJed Brown /// // Coarse problem 17709df49d7eSJed Brown /// u_coarse.set_value(1.0); 1771c68be7a2SJeremy L Thompson /// op_mass_coarse.apply(&u_coarse, &mut v_coarse)?; 17729df49d7eSJed Brown /// 17739df49d7eSJed Brown /// // Check 1774e78171edSJeremy L Thompson /// let sum: Scalar = v_coarse.view()?.iter().sum(); 17759df49d7eSJed Brown /// assert!( 177680a9ef05SNatalie Beams /// (sum - 2.0).abs() < 10.0 * libceed::EPSILON, 17779df49d7eSJed Brown /// "Incorrect interval length computed" 17789df49d7eSJed Brown /// ); 17799df49d7eSJed Brown /// 17809df49d7eSJed Brown /// // Prolong 1781c68be7a2SJeremy L Thompson /// op_prolong.apply(&u_coarse, &mut u_fine)?; 17829df49d7eSJed Brown /// 17839df49d7eSJed Brown /// // Fine problem 1784c68be7a2SJeremy L Thompson /// op_mass_fine.apply(&u_fine, &mut v_fine)?; 17859df49d7eSJed Brown /// 17869df49d7eSJed Brown /// // Check 1787e78171edSJeremy L Thompson /// let sum: Scalar = v_fine.view()?.iter().sum(); 17889df49d7eSJed Brown /// assert!( 178980a9ef05SNatalie Beams /// (sum - 2.0).abs() < 10.0 * libceed::EPSILON, 17909df49d7eSJed Brown /// "Incorrect interval length computed" 17919df49d7eSJed Brown /// ); 17929df49d7eSJed Brown /// 17939df49d7eSJed Brown /// // Restrict 1794c68be7a2SJeremy L Thompson /// op_restrict.apply(&v_fine, &mut v_coarse)?; 17959df49d7eSJed Brown /// 17969df49d7eSJed Brown /// // Check 1797e78171edSJeremy L Thompson /// let sum: Scalar = v_coarse.view()?.iter().sum(); 17989df49d7eSJed Brown /// assert!( 179980a9ef05SNatalie Beams /// (sum - 2.0).abs() < 10.0 * libceed::EPSILON, 18009df49d7eSJed Brown /// "Incorrect interval length computed" 18019df49d7eSJed Brown /// ); 1802c68be7a2SJeremy L Thompson /// # Ok(()) 1803c68be7a2SJeremy L Thompson /// # } 18049df49d7eSJed Brown /// ``` 18059df49d7eSJed Brown pub fn create_multigrid_level_tensor_H1( 18069df49d7eSJed Brown &self, 18079df49d7eSJed Brown p_mult_fine: &Vector, 18089df49d7eSJed Brown rstr_coarse: &ElemRestriction, 18099df49d7eSJed Brown basis_coarse: &Basis, 181080a9ef05SNatalie Beams interpCtoF: &Vec<Scalar>, 18119df49d7eSJed Brown ) -> crate::Result<(Operator, Operator, Operator)> { 18129df49d7eSJed Brown let mut ptr_coarse = std::ptr::null_mut(); 18139df49d7eSJed Brown let mut ptr_prolong = std::ptr::null_mut(); 18149df49d7eSJed Brown let mut ptr_restrict = std::ptr::null_mut(); 18159df49d7eSJed Brown let ierr = unsafe { 18169df49d7eSJed Brown bind_ceed::CeedOperatorMultigridLevelCreateTensorH1( 18179df49d7eSJed Brown self.op_core.ptr, 18189df49d7eSJed Brown p_mult_fine.ptr, 18199df49d7eSJed Brown rstr_coarse.ptr, 18209df49d7eSJed Brown basis_coarse.ptr, 18219df49d7eSJed Brown interpCtoF.as_ptr(), 18229df49d7eSJed Brown &mut ptr_coarse, 18239df49d7eSJed Brown &mut ptr_prolong, 18249df49d7eSJed Brown &mut ptr_restrict, 18259df49d7eSJed Brown ) 18269df49d7eSJed Brown }; 18271142270cSJeremy L Thompson self.op_core.check_error(ierr)?; 18281142270cSJeremy L Thompson let op_coarse = Operator::from_raw(ptr_coarse)?; 18291142270cSJeremy L Thompson let op_prolong = Operator::from_raw(ptr_prolong)?; 18301142270cSJeremy L Thompson let op_restrict = Operator::from_raw(ptr_restrict)?; 18319df49d7eSJed Brown Ok((op_coarse, op_prolong, op_restrict)) 18329df49d7eSJed Brown } 18339df49d7eSJed Brown 18349df49d7eSJed Brown /// Create a multigrid coarse Operator and level transfer Operators for a 18359df49d7eSJed Brown /// given Operator with a non-tensor basis for the active basis 18369df49d7eSJed Brown /// 18379df49d7eSJed Brown /// * `p_mult_fine` - Lvector multiplicity in parallel gather/scatter 18389df49d7eSJed Brown /// * `rstr_coarse` - Coarse grid restriction 18399df49d7eSJed Brown /// * `basis_coarse` - Coarse grid active vector basis 18409df49d7eSJed Brown /// * `interp_c_to_f` - Matrix for coarse to fine 18419df49d7eSJed Brown /// 18429df49d7eSJed Brown /// ``` 18439df49d7eSJed Brown /// # use libceed::prelude::*; 18444d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 18459df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 18469df49d7eSJed Brown /// let ne = 15; 18479df49d7eSJed Brown /// let p_coarse = 3; 18489df49d7eSJed Brown /// let p_fine = 5; 18499df49d7eSJed Brown /// let q = 6; 18509df49d7eSJed Brown /// let ndofs_coarse = p_coarse * ne - ne + 1; 18519df49d7eSJed Brown /// let ndofs_fine = p_fine * ne - ne + 1; 18529df49d7eSJed Brown /// 18539df49d7eSJed Brown /// // Vectors 18549df49d7eSJed Brown /// let x_array = (0..ne + 1) 185580a9ef05SNatalie Beams /// .map(|i| 2.0 * i as Scalar / ne as Scalar - 1.0) 185680a9ef05SNatalie Beams /// .collect::<Vec<Scalar>>(); 1857c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&x_array)?; 1858c68be7a2SJeremy L Thompson /// let mut qdata = ceed.vector(ne * q)?; 18599df49d7eSJed Brown /// qdata.set_value(0.0); 1860c68be7a2SJeremy L Thompson /// let mut u_coarse = ceed.vector(ndofs_coarse)?; 18619df49d7eSJed Brown /// u_coarse.set_value(1.0); 1862c68be7a2SJeremy L Thompson /// let mut u_fine = ceed.vector(ndofs_fine)?; 18639df49d7eSJed Brown /// u_fine.set_value(1.0); 1864c68be7a2SJeremy L Thompson /// let mut v_coarse = ceed.vector(ndofs_coarse)?; 18659df49d7eSJed Brown /// v_coarse.set_value(0.0); 1866c68be7a2SJeremy L Thompson /// let mut v_fine = ceed.vector(ndofs_fine)?; 18679df49d7eSJed Brown /// v_fine.set_value(0.0); 1868c68be7a2SJeremy L Thompson /// let mut multiplicity = ceed.vector(ndofs_fine)?; 18699df49d7eSJed Brown /// multiplicity.set_value(1.0); 18709df49d7eSJed Brown /// 18719df49d7eSJed Brown /// // Restrictions 18729df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 1873c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 18749df49d7eSJed Brown /// 18759df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 18769df49d7eSJed Brown /// for i in 0..ne { 18779df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 18789df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 18799df49d7eSJed Brown /// } 1880c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 18819df49d7eSJed Brown /// 18829df49d7eSJed Brown /// let mut indu_coarse: Vec<i32> = vec![0; p_coarse * ne]; 18839df49d7eSJed Brown /// for i in 0..ne { 18849df49d7eSJed Brown /// for j in 0..p_coarse { 18859df49d7eSJed Brown /// indu_coarse[p_coarse * i + j] = (i + j) as i32; 18869df49d7eSJed Brown /// } 18879df49d7eSJed Brown /// } 1888c68be7a2SJeremy L Thompson /// let ru_coarse = ceed.elem_restriction( 18899df49d7eSJed Brown /// ne, 18909df49d7eSJed Brown /// p_coarse, 18919df49d7eSJed Brown /// 1, 18929df49d7eSJed Brown /// 1, 18939df49d7eSJed Brown /// ndofs_coarse, 18949df49d7eSJed Brown /// MemType::Host, 18959df49d7eSJed Brown /// &indu_coarse, 1896c68be7a2SJeremy L Thompson /// )?; 18979df49d7eSJed Brown /// 18989df49d7eSJed Brown /// let mut indu_fine: Vec<i32> = vec![0; p_fine * ne]; 18999df49d7eSJed Brown /// for i in 0..ne { 19009df49d7eSJed Brown /// for j in 0..p_fine { 19019df49d7eSJed Brown /// indu_fine[p_fine * i + j] = (i + j) as i32; 19029df49d7eSJed Brown /// } 19039df49d7eSJed Brown /// } 1904c68be7a2SJeremy L Thompson /// let ru_fine = ceed.elem_restriction(ne, p_fine, 1, 1, ndofs_fine, MemType::Host, &indu_fine)?; 19059df49d7eSJed Brown /// 19069df49d7eSJed Brown /// // Bases 1907c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 1908c68be7a2SJeremy L Thompson /// let bu_coarse = ceed.basis_tensor_H1_Lagrange(1, 1, p_coarse, q, QuadMode::Gauss)?; 1909c68be7a2SJeremy L Thompson /// let bu_fine = ceed.basis_tensor_H1_Lagrange(1, 1, p_fine, q, QuadMode::Gauss)?; 19109df49d7eSJed Brown /// 19119df49d7eSJed Brown /// // Build quadrature data 1912c68be7a2SJeremy L Thompson /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 1913c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 1914c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 1915c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 1916c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)? 1917c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata)?; 19189df49d7eSJed Brown /// 19199df49d7eSJed Brown /// // Mass operator 1920c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 19219df49d7eSJed Brown /// let op_mass_fine = ceed 1922c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 1923c68be7a2SJeremy L Thompson /// .field("u", &ru_fine, &bu_fine, VectorOpt::Active)? 1924c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, &qdata)? 1925c68be7a2SJeremy L Thompson /// .field("v", &ru_fine, &bu_fine, VectorOpt::Active)?; 19269df49d7eSJed Brown /// 19279df49d7eSJed Brown /// // Multigrid setup 192880a9ef05SNatalie Beams /// let mut interp_c_to_f: Vec<Scalar> = vec![0.; p_coarse * p_fine]; 19299df49d7eSJed Brown /// { 1930c68be7a2SJeremy L Thompson /// let mut coarse = ceed.vector(p_coarse)?; 1931c68be7a2SJeremy L Thompson /// let mut fine = ceed.vector(p_fine)?; 1932c68be7a2SJeremy L Thompson /// let basis_c_to_f = 1933c68be7a2SJeremy L Thompson /// ceed.basis_tensor_H1_Lagrange(1, 1, p_coarse, p_fine, QuadMode::GaussLobatto)?; 19349df49d7eSJed Brown /// for i in 0..p_coarse { 19359df49d7eSJed Brown /// coarse.set_value(0.0); 19369df49d7eSJed Brown /// { 1937e78171edSJeremy L Thompson /// let mut array = coarse.view_mut()?; 19389df49d7eSJed Brown /// array[i] = 1.; 19399df49d7eSJed Brown /// } 1940c68be7a2SJeremy L Thompson /// basis_c_to_f.apply( 19419df49d7eSJed Brown /// 1, 19429df49d7eSJed Brown /// TransposeMode::NoTranspose, 19439df49d7eSJed Brown /// EvalMode::Interp, 19449df49d7eSJed Brown /// &coarse, 19459df49d7eSJed Brown /// &mut fine, 1946c68be7a2SJeremy L Thompson /// )?; 1947e78171edSJeremy L Thompson /// let array = fine.view()?; 19489df49d7eSJed Brown /// for j in 0..p_fine { 19499df49d7eSJed Brown /// interp_c_to_f[j * p_coarse + i] = array[j]; 19509df49d7eSJed Brown /// } 19519df49d7eSJed Brown /// } 19529df49d7eSJed Brown /// } 1953c68be7a2SJeremy L Thompson /// let (op_mass_coarse, op_prolong, op_restrict) = op_mass_fine.create_multigrid_level_H1( 1954c68be7a2SJeremy L Thompson /// &multiplicity, 1955c68be7a2SJeremy L Thompson /// &ru_coarse, 1956c68be7a2SJeremy L Thompson /// &bu_coarse, 1957c68be7a2SJeremy L Thompson /// &interp_c_to_f, 1958c68be7a2SJeremy L Thompson /// )?; 19599df49d7eSJed Brown /// 19609df49d7eSJed Brown /// // Coarse problem 19619df49d7eSJed Brown /// u_coarse.set_value(1.0); 1962c68be7a2SJeremy L Thompson /// op_mass_coarse.apply(&u_coarse, &mut v_coarse)?; 19639df49d7eSJed Brown /// 19649df49d7eSJed Brown /// // Check 1965e78171edSJeremy L Thompson /// let sum: Scalar = v_coarse.view()?.iter().sum(); 19669df49d7eSJed Brown /// assert!( 196780a9ef05SNatalie Beams /// (sum - 2.0).abs() < 10.0 * libceed::EPSILON, 19689df49d7eSJed Brown /// "Incorrect interval length computed" 19699df49d7eSJed Brown /// ); 19709df49d7eSJed Brown /// 19719df49d7eSJed Brown /// // Prolong 1972c68be7a2SJeremy L Thompson /// op_prolong.apply(&u_coarse, &mut u_fine)?; 19739df49d7eSJed Brown /// 19749df49d7eSJed Brown /// // Fine problem 1975c68be7a2SJeremy L Thompson /// op_mass_fine.apply(&u_fine, &mut v_fine)?; 19769df49d7eSJed Brown /// 19779df49d7eSJed Brown /// // Check 1978e78171edSJeremy L Thompson /// let sum: Scalar = v_fine.view()?.iter().sum(); 19799df49d7eSJed Brown /// assert!( 198080a9ef05SNatalie Beams /// (sum - 2.0).abs() < 10.0 * libceed::EPSILON, 19819df49d7eSJed Brown /// "Incorrect interval length computed" 19829df49d7eSJed Brown /// ); 19839df49d7eSJed Brown /// 19849df49d7eSJed Brown /// // Restrict 1985c68be7a2SJeremy L Thompson /// op_restrict.apply(&v_fine, &mut v_coarse)?; 19869df49d7eSJed Brown /// 19879df49d7eSJed Brown /// // Check 1988e78171edSJeremy L Thompson /// let sum: Scalar = v_coarse.view()?.iter().sum(); 19899df49d7eSJed Brown /// assert!( 199080a9ef05SNatalie Beams /// (sum - 2.0).abs() < 10.0 * libceed::EPSILON, 19919df49d7eSJed Brown /// "Incorrect interval length computed" 19929df49d7eSJed Brown /// ); 1993c68be7a2SJeremy L Thompson /// # Ok(()) 1994c68be7a2SJeremy L Thompson /// # } 19959df49d7eSJed Brown /// ``` 19969df49d7eSJed Brown pub fn create_multigrid_level_H1( 19979df49d7eSJed Brown &self, 19989df49d7eSJed Brown p_mult_fine: &Vector, 19999df49d7eSJed Brown rstr_coarse: &ElemRestriction, 20009df49d7eSJed Brown basis_coarse: &Basis, 200180a9ef05SNatalie Beams interpCtoF: &[Scalar], 20029df49d7eSJed Brown ) -> crate::Result<(Operator, Operator, Operator)> { 20039df49d7eSJed Brown let mut ptr_coarse = std::ptr::null_mut(); 20049df49d7eSJed Brown let mut ptr_prolong = std::ptr::null_mut(); 20059df49d7eSJed Brown let mut ptr_restrict = std::ptr::null_mut(); 20069df49d7eSJed Brown let ierr = unsafe { 20079df49d7eSJed Brown bind_ceed::CeedOperatorMultigridLevelCreateH1( 20089df49d7eSJed Brown self.op_core.ptr, 20099df49d7eSJed Brown p_mult_fine.ptr, 20109df49d7eSJed Brown rstr_coarse.ptr, 20119df49d7eSJed Brown basis_coarse.ptr, 20129df49d7eSJed Brown interpCtoF.as_ptr(), 20139df49d7eSJed Brown &mut ptr_coarse, 20149df49d7eSJed Brown &mut ptr_prolong, 20159df49d7eSJed Brown &mut ptr_restrict, 20169df49d7eSJed Brown ) 20179df49d7eSJed Brown }; 20181142270cSJeremy L Thompson self.op_core.check_error(ierr)?; 20191142270cSJeremy L Thompson let op_coarse = Operator::from_raw(ptr_coarse)?; 20201142270cSJeremy L Thompson let op_prolong = Operator::from_raw(ptr_prolong)?; 20211142270cSJeremy L Thompson let op_restrict = Operator::from_raw(ptr_restrict)?; 20229df49d7eSJed Brown Ok((op_coarse, op_prolong, op_restrict)) 20239df49d7eSJed Brown } 20249df49d7eSJed Brown } 20259df49d7eSJed Brown 20269df49d7eSJed Brown // ----------------------------------------------------------------------------- 20279df49d7eSJed Brown // Composite Operator 20289df49d7eSJed Brown // ----------------------------------------------------------------------------- 20299df49d7eSJed Brown impl<'a> CompositeOperator<'a> { 20309df49d7eSJed Brown // Constructor 20319df49d7eSJed Brown pub fn create(ceed: &'a crate::Ceed) -> crate::Result<Self> { 20329df49d7eSJed Brown let mut ptr = std::ptr::null_mut(); 20339df49d7eSJed Brown let ierr = unsafe { bind_ceed::CeedCompositeOperatorCreate(ceed.ptr, &mut ptr) }; 20349df49d7eSJed Brown ceed.check_error(ierr)?; 20359df49d7eSJed Brown Ok(Self { 20361142270cSJeremy L Thompson op_core: OperatorCore { 20371142270cSJeremy L Thompson ptr, 20381142270cSJeremy L Thompson _lifeline: PhantomData, 20391142270cSJeremy L Thompson }, 20409df49d7eSJed Brown }) 20419df49d7eSJed Brown } 20429df49d7eSJed Brown 20439df49d7eSJed Brown /// Apply Operator to a vector 20449df49d7eSJed Brown /// 20459df49d7eSJed Brown /// * `input` - Input Vector 20469df49d7eSJed Brown /// * `output` - Output Vector 20479df49d7eSJed Brown /// 20489df49d7eSJed Brown /// ``` 20499df49d7eSJed Brown /// # use libceed::prelude::*; 20504d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 20519df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 20529df49d7eSJed Brown /// let ne = 4; 20539df49d7eSJed Brown /// let p = 3; 20549df49d7eSJed Brown /// let q = 4; 20559df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 20569df49d7eSJed Brown /// 20579df49d7eSJed Brown /// // Vectors 2058c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0])?; 2059c68be7a2SJeremy L Thompson /// let mut qdata_mass = ceed.vector(ne * q)?; 20609df49d7eSJed Brown /// qdata_mass.set_value(0.0); 2061c68be7a2SJeremy L Thompson /// let mut qdata_diff = ceed.vector(ne * q)?; 20629df49d7eSJed Brown /// qdata_diff.set_value(0.0); 2063c68be7a2SJeremy L Thompson /// let mut u = ceed.vector(ndofs)?; 20649df49d7eSJed Brown /// u.set_value(1.0); 2065c68be7a2SJeremy L Thompson /// let mut v = ceed.vector(ndofs)?; 20669df49d7eSJed Brown /// v.set_value(0.0); 20679df49d7eSJed Brown /// 20689df49d7eSJed Brown /// // Restrictions 20699df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 20709df49d7eSJed Brown /// for i in 0..ne { 20719df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 20729df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 20739df49d7eSJed Brown /// } 2074c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 20759df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 20769df49d7eSJed Brown /// for i in 0..ne { 20779df49d7eSJed Brown /// indu[p * i + 0] = i as i32; 20789df49d7eSJed Brown /// indu[p * i + 1] = (i + 1) as i32; 20799df49d7eSJed Brown /// indu[p * i + 2] = (i + 2) as i32; 20809df49d7eSJed Brown /// } 2081c68be7a2SJeremy L Thompson /// let ru = ceed.elem_restriction(ne, 3, 1, 1, ndofs, MemType::Host, &indu)?; 20829df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 2083c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 20849df49d7eSJed Brown /// 20859df49d7eSJed Brown /// // Bases 2086c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 2087c68be7a2SJeremy L Thompson /// let bu = ceed.basis_tensor_H1_Lagrange(1, 1, p, q, QuadMode::Gauss)?; 20889df49d7eSJed Brown /// 20899df49d7eSJed Brown /// // Build quadrature data 2090c68be7a2SJeremy L Thompson /// let qf_build_mass = ceed.q_function_interior_by_name("Mass1DBuild")?; 2091c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build_mass, QFunctionOpt::None, QFunctionOpt::None)? 2092c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 2093c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 2094c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)? 2095c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata_mass)?; 20969df49d7eSJed Brown /// 2097c68be7a2SJeremy L Thompson /// let qf_build_diff = ceed.q_function_interior_by_name("Poisson1DBuild")?; 2098c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build_diff, QFunctionOpt::None, QFunctionOpt::None)? 2099c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 2100c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 2101c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)? 2102c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata_diff)?; 21039df49d7eSJed Brown /// 21049df49d7eSJed Brown /// // Application operator 2105c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 21069df49d7eSJed Brown /// let op_mass = ceed 2107c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 2108c68be7a2SJeremy L Thompson /// .field("u", &ru, &bu, VectorOpt::Active)? 2109c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, &qdata_mass)? 2110c68be7a2SJeremy L Thompson /// .field("v", &ru, &bu, VectorOpt::Active)?; 21119df49d7eSJed Brown /// 2112c68be7a2SJeremy L Thompson /// let qf_diff = ceed.q_function_interior_by_name("Poisson1DApply")?; 21139df49d7eSJed Brown /// let op_diff = ceed 2114c68be7a2SJeremy L Thompson /// .operator(&qf_diff, QFunctionOpt::None, QFunctionOpt::None)? 2115c68be7a2SJeremy L Thompson /// .field("du", &ru, &bu, VectorOpt::Active)? 2116c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, &qdata_diff)? 2117c68be7a2SJeremy L Thompson /// .field("dv", &ru, &bu, VectorOpt::Active)?; 21189df49d7eSJed Brown /// 21199df49d7eSJed Brown /// let op_composite = ceed 2120c68be7a2SJeremy L Thompson /// .composite_operator()? 2121c68be7a2SJeremy L Thompson /// .sub_operator(&op_mass)? 2122c68be7a2SJeremy L Thompson /// .sub_operator(&op_diff)?; 21239df49d7eSJed Brown /// 21249df49d7eSJed Brown /// v.set_value(0.0); 2125c68be7a2SJeremy L Thompson /// op_composite.apply(&u, &mut v)?; 21269df49d7eSJed Brown /// 21279df49d7eSJed Brown /// // Check 2128e78171edSJeremy L Thompson /// let sum: Scalar = v.view()?.iter().sum(); 21299df49d7eSJed Brown /// assert!( 213080a9ef05SNatalie Beams /// (sum - 2.0).abs() < 10.0 * libceed::EPSILON, 21319df49d7eSJed Brown /// "Incorrect interval length computed" 21329df49d7eSJed Brown /// ); 2133c68be7a2SJeremy L Thompson /// # Ok(()) 2134c68be7a2SJeremy L Thompson /// # } 21359df49d7eSJed Brown /// ``` 21369df49d7eSJed Brown pub fn apply(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> { 21379df49d7eSJed Brown self.op_core.apply(input, output) 21389df49d7eSJed Brown } 21399df49d7eSJed Brown 21409df49d7eSJed Brown /// Apply Operator to a vector and add result to output vector 21419df49d7eSJed Brown /// 21429df49d7eSJed Brown /// * `input` - Input Vector 21439df49d7eSJed Brown /// * `output` - Output Vector 21449df49d7eSJed Brown /// 21459df49d7eSJed Brown /// ``` 21469df49d7eSJed Brown /// # use libceed::prelude::*; 21474d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 21489df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 21499df49d7eSJed Brown /// let ne = 4; 21509df49d7eSJed Brown /// let p = 3; 21519df49d7eSJed Brown /// let q = 4; 21529df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 21539df49d7eSJed Brown /// 21549df49d7eSJed Brown /// // Vectors 2155c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0])?; 2156c68be7a2SJeremy L Thompson /// let mut qdata_mass = ceed.vector(ne * q)?; 21579df49d7eSJed Brown /// qdata_mass.set_value(0.0); 2158c68be7a2SJeremy L Thompson /// let mut qdata_diff = ceed.vector(ne * q)?; 21599df49d7eSJed Brown /// qdata_diff.set_value(0.0); 2160c68be7a2SJeremy L Thompson /// let mut u = ceed.vector(ndofs)?; 21619df49d7eSJed Brown /// u.set_value(1.0); 2162c68be7a2SJeremy L Thompson /// let mut v = ceed.vector(ndofs)?; 21639df49d7eSJed Brown /// v.set_value(0.0); 21649df49d7eSJed Brown /// 21659df49d7eSJed Brown /// // Restrictions 21669df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 21679df49d7eSJed Brown /// for i in 0..ne { 21689df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 21699df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 21709df49d7eSJed Brown /// } 2171c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 21729df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 21739df49d7eSJed Brown /// for i in 0..ne { 21749df49d7eSJed Brown /// indu[p * i + 0] = i as i32; 21759df49d7eSJed Brown /// indu[p * i + 1] = (i + 1) as i32; 21769df49d7eSJed Brown /// indu[p * i + 2] = (i + 2) as i32; 21779df49d7eSJed Brown /// } 2178c68be7a2SJeremy L Thompson /// let ru = ceed.elem_restriction(ne, 3, 1, 1, ndofs, MemType::Host, &indu)?; 21799df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 2180c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 21819df49d7eSJed Brown /// 21829df49d7eSJed Brown /// // Bases 2183c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 2184c68be7a2SJeremy L Thompson /// let bu = ceed.basis_tensor_H1_Lagrange(1, 1, p, q, QuadMode::Gauss)?; 21859df49d7eSJed Brown /// 21869df49d7eSJed Brown /// // Build quadrature data 2187c68be7a2SJeremy L Thompson /// let qf_build_mass = ceed.q_function_interior_by_name("Mass1DBuild")?; 2188c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build_mass, QFunctionOpt::None, QFunctionOpt::None)? 2189c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 2190c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 2191c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)? 2192c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata_mass)?; 21939df49d7eSJed Brown /// 2194c68be7a2SJeremy L Thompson /// let qf_build_diff = ceed.q_function_interior_by_name("Poisson1DBuild")?; 2195c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build_diff, QFunctionOpt::None, QFunctionOpt::None)? 2196c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 2197c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 2198c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)? 2199c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata_diff)?; 22009df49d7eSJed Brown /// 22019df49d7eSJed Brown /// // Application operator 2202c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 22039df49d7eSJed Brown /// let op_mass = ceed 2204c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 2205c68be7a2SJeremy L Thompson /// .field("u", &ru, &bu, VectorOpt::Active)? 2206c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, &qdata_mass)? 2207c68be7a2SJeremy L Thompson /// .field("v", &ru, &bu, VectorOpt::Active)?; 22089df49d7eSJed Brown /// 2209c68be7a2SJeremy L Thompson /// let qf_diff = ceed.q_function_interior_by_name("Poisson1DApply")?; 22109df49d7eSJed Brown /// let op_diff = ceed 2211c68be7a2SJeremy L Thompson /// .operator(&qf_diff, QFunctionOpt::None, QFunctionOpt::None)? 2212c68be7a2SJeremy L Thompson /// .field("du", &ru, &bu, VectorOpt::Active)? 2213c68be7a2SJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, &qdata_diff)? 2214c68be7a2SJeremy L Thompson /// .field("dv", &ru, &bu, VectorOpt::Active)?; 22159df49d7eSJed Brown /// 22169df49d7eSJed Brown /// let op_composite = ceed 2217c68be7a2SJeremy L Thompson /// .composite_operator()? 2218c68be7a2SJeremy L Thompson /// .sub_operator(&op_mass)? 2219c68be7a2SJeremy L Thompson /// .sub_operator(&op_diff)?; 22209df49d7eSJed Brown /// 22219df49d7eSJed Brown /// v.set_value(1.0); 2222c68be7a2SJeremy L Thompson /// op_composite.apply_add(&u, &mut v)?; 22239df49d7eSJed Brown /// 22249df49d7eSJed Brown /// // Check 2225e78171edSJeremy L Thompson /// let sum: Scalar = v.view()?.iter().sum(); 22269df49d7eSJed Brown /// assert!( 222780a9ef05SNatalie Beams /// (sum - (2.0 + ndofs as Scalar)).abs() < 10.0 * libceed::EPSILON, 22289df49d7eSJed Brown /// "Incorrect interval length computed" 22299df49d7eSJed Brown /// ); 2230c68be7a2SJeremy L Thompson /// # Ok(()) 2231c68be7a2SJeremy L Thompson /// # } 22329df49d7eSJed Brown /// ``` 22339df49d7eSJed Brown pub fn apply_add(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> { 22349df49d7eSJed Brown self.op_core.apply_add(input, output) 22359df49d7eSJed Brown } 22369df49d7eSJed Brown 22379df49d7eSJed Brown /// Add a sub-Operator to a Composite Operator 22389df49d7eSJed Brown /// 22399df49d7eSJed Brown /// * `subop` - Sub-Operator 22409df49d7eSJed Brown /// 22419df49d7eSJed Brown /// ``` 22429df49d7eSJed Brown /// # use libceed::prelude::*; 22434d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 22449df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 2245c68be7a2SJeremy L Thompson /// let mut op = ceed.composite_operator()?; 22469df49d7eSJed Brown /// 2247c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 2248c68be7a2SJeremy L Thompson /// let op_mass = ceed.operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)?; 2249c68be7a2SJeremy L Thompson /// op = op.sub_operator(&op_mass)?; 22509df49d7eSJed Brown /// 2251c68be7a2SJeremy L Thompson /// let qf_diff = ceed.q_function_interior_by_name("Poisson1DApply")?; 2252c68be7a2SJeremy L Thompson /// let op_diff = ceed.operator(&qf_diff, QFunctionOpt::None, QFunctionOpt::None)?; 2253c68be7a2SJeremy L Thompson /// op = op.sub_operator(&op_diff)?; 2254c68be7a2SJeremy L Thompson /// # Ok(()) 2255c68be7a2SJeremy L Thompson /// # } 22569df49d7eSJed Brown /// ``` 22579df49d7eSJed Brown #[allow(unused_mut)] 22589df49d7eSJed Brown pub fn sub_operator(mut self, subop: &Operator) -> crate::Result<Self> { 22599df49d7eSJed Brown let ierr = 22609df49d7eSJed Brown unsafe { bind_ceed::CeedCompositeOperatorAddSub(self.op_core.ptr, subop.op_core.ptr) }; 22611142270cSJeremy L Thompson self.op_core.check_error(ierr)?; 22629df49d7eSJed Brown Ok(self) 22639df49d7eSJed Brown } 22649df49d7eSJed Brown 2265*6f97ff0aSJeremy L Thompson /// Check if CompositeOperator is setup correctly 2266*6f97ff0aSJeremy L Thompson /// 2267*6f97ff0aSJeremy L Thompson /// ``` 2268*6f97ff0aSJeremy L Thompson /// # use libceed::prelude::*; 2269*6f97ff0aSJeremy L Thompson /// # fn main() -> libceed::Result<()> { 2270*6f97ff0aSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 2271*6f97ff0aSJeremy L Thompson /// let ne = 4; 2272*6f97ff0aSJeremy L Thompson /// let p = 3; 2273*6f97ff0aSJeremy L Thompson /// let q = 4; 2274*6f97ff0aSJeremy L Thompson /// let ndofs = p * ne - ne + 1; 2275*6f97ff0aSJeremy L Thompson /// 2276*6f97ff0aSJeremy L Thompson /// // Restrictions 2277*6f97ff0aSJeremy L Thompson /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 2278*6f97ff0aSJeremy L Thompson /// for i in 0..ne { 2279*6f97ff0aSJeremy L Thompson /// indx[2 * i + 0] = i as i32; 2280*6f97ff0aSJeremy L Thompson /// indx[2 * i + 1] = (i + 1) as i32; 2281*6f97ff0aSJeremy L Thompson /// } 2282*6f97ff0aSJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 2283*6f97ff0aSJeremy L Thompson /// let strides: [i32; 3] = [1, q as i32, q as i32]; 2284*6f97ff0aSJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 2285*6f97ff0aSJeremy L Thompson /// 2286*6f97ff0aSJeremy L Thompson /// // Bases 2287*6f97ff0aSJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 2288*6f97ff0aSJeremy L Thompson /// 2289*6f97ff0aSJeremy L Thompson /// // Build quadrature data 2290*6f97ff0aSJeremy L Thompson /// let qf_build_mass = ceed.q_function_interior_by_name("Mass1DBuild")?; 2291*6f97ff0aSJeremy L Thompson /// let op_build_mass = ceed 2292*6f97ff0aSJeremy L Thompson /// .operator(&qf_build_mass, QFunctionOpt::None, QFunctionOpt::None)? 2293*6f97ff0aSJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 2294*6f97ff0aSJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 2295*6f97ff0aSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)?; 2296*6f97ff0aSJeremy L Thompson /// 2297*6f97ff0aSJeremy L Thompson /// let qf_build_diff = ceed.q_function_interior_by_name("Poisson1DBuild")?; 2298*6f97ff0aSJeremy L Thompson /// let op_build_diff = ceed 2299*6f97ff0aSJeremy L Thompson /// .operator(&qf_build_diff, QFunctionOpt::None, QFunctionOpt::None)? 2300*6f97ff0aSJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 2301*6f97ff0aSJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 2302*6f97ff0aSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active)?; 2303*6f97ff0aSJeremy L Thompson /// 2304*6f97ff0aSJeremy L Thompson /// let op_build = ceed 2305*6f97ff0aSJeremy L Thompson /// .composite_operator()? 2306*6f97ff0aSJeremy L Thompson /// .sub_operator(&op_build_mass)? 2307*6f97ff0aSJeremy L Thompson /// .sub_operator(&op_build_diff)?; 2308*6f97ff0aSJeremy L Thompson /// 2309*6f97ff0aSJeremy L Thompson /// // Check 2310*6f97ff0aSJeremy L Thompson /// assert!(op_build.check().is_ok(), "Operator setup incorrectly"); 2311*6f97ff0aSJeremy L Thompson /// # Ok(()) 2312*6f97ff0aSJeremy L Thompson /// # } 2313*6f97ff0aSJeremy L Thompson /// ``` 2314*6f97ff0aSJeremy L Thompson pub fn check(self) -> crate::Result<Self> { 2315*6f97ff0aSJeremy L Thompson self.op_core.check()?; 2316*6f97ff0aSJeremy L Thompson Ok(self) 2317*6f97ff0aSJeremy L Thompson } 2318*6f97ff0aSJeremy L Thompson 23199df49d7eSJed Brown /// Assemble the diagonal of a square linear Operator 23209df49d7eSJed Brown /// 23219df49d7eSJed Brown /// This overwrites a Vector with the diagonal of a linear Operator. 23229df49d7eSJed Brown /// 23239df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 23249df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 23259df49d7eSJed Brown /// 23269df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 23279df49d7eSJed Brown /// * `assembled` - Vector to store assembled Operator diagonal 23289df49d7eSJed Brown pub fn linear_asssemble_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> { 23299df49d7eSJed Brown self.op_core.linear_assemble_add_diagonal(assembled) 23309df49d7eSJed Brown } 23319df49d7eSJed Brown 23329df49d7eSJed Brown /// Assemble the point block diagonal of a square linear Operator 23339df49d7eSJed Brown /// 23349df49d7eSJed Brown /// This overwrites a Vector with the point block diagonal of a linear 23359df49d7eSJed Brown /// Operator. 23369df49d7eSJed Brown /// 23379df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 23389df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 23399df49d7eSJed Brown /// 23409df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 23419df49d7eSJed Brown /// * `assembled` - Vector to store assembled Operator diagonal 23429df49d7eSJed Brown pub fn linear_assemble_add_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> { 23439df49d7eSJed Brown self.op_core.linear_assemble_add_diagonal(assembled) 23449df49d7eSJed Brown } 23459df49d7eSJed Brown 23469df49d7eSJed Brown /// Assemble the diagonal of a square linear Operator 23479df49d7eSJed Brown /// 23489df49d7eSJed Brown /// This overwrites a Vector with the diagonal of a linear Operator. 23499df49d7eSJed Brown /// 23509df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 23519df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 23529df49d7eSJed Brown /// 23539df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 23549df49d7eSJed Brown /// * `assembled` - Vector to store assembled CeedOperator point block 23559df49d7eSJed Brown /// diagonal, provided in row-major form with an 23569df49d7eSJed Brown /// `ncomp * ncomp` block at each node. The dimensions of 23579df49d7eSJed Brown /// this vector are derived from the active vector for 23589df49d7eSJed Brown /// the CeedOperator. The array has shape 23599df49d7eSJed Brown /// `[nodes, component out, component in]`. 23609df49d7eSJed Brown pub fn linear_assemble_point_block_diagonal( 23619df49d7eSJed Brown &self, 23629df49d7eSJed Brown assembled: &mut Vector, 23639df49d7eSJed Brown ) -> crate::Result<i32> { 23649df49d7eSJed Brown self.op_core.linear_assemble_add_diagonal(assembled) 23659df49d7eSJed Brown } 23669df49d7eSJed Brown 23679df49d7eSJed Brown /// Assemble the diagonal of a square linear Operator 23689df49d7eSJed Brown /// 23699df49d7eSJed Brown /// This sums into a Vector with the diagonal of a linear Operator. 23709df49d7eSJed Brown /// 23719df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 23729df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 23739df49d7eSJed Brown /// 23749df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 23759df49d7eSJed Brown /// * `assembled` - Vector to store assembled CeedOperator point block 23769df49d7eSJed Brown /// diagonal, provided in row-major form with an 23779df49d7eSJed Brown /// `ncomp * ncomp` block at each node. The dimensions of 23789df49d7eSJed Brown /// this vector are derived from the active vector for 23799df49d7eSJed Brown /// the CeedOperator. The array has shape 23809df49d7eSJed Brown /// `[nodes, component out, component in]`. 23819df49d7eSJed Brown pub fn linear_assemble_add_point_block_diagonal( 23829df49d7eSJed Brown &self, 23839df49d7eSJed Brown assembled: &mut Vector, 23849df49d7eSJed Brown ) -> crate::Result<i32> { 23859df49d7eSJed Brown self.op_core.linear_assemble_add_diagonal(assembled) 23869df49d7eSJed Brown } 23879df49d7eSJed Brown } 23889df49d7eSJed Brown 23899df49d7eSJed Brown // ----------------------------------------------------------------------------- 2390