1*9ba83ac0SJeremy L Thompson // Copyright (c) 2017-2026, Lawrence Livermore National Security, LLC and other CEED contributors. 23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 39df49d7eSJed Brown // 43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 59df49d7eSJed Brown // 63d8e8822SJeremy L Thompson // This file is part of CEED: http://github.com/ceed 79df49d7eSJed Brown 89df49d7eSJed Brown //! A Ceed Operator defines the finite/spectral element operator associated to a 99df49d7eSJed Brown //! Ceed QFunction. A Ceed Operator connects Ceed ElemRestrictions, 109df49d7eSJed Brown //! Ceed Bases, and Ceed QFunctions. 119df49d7eSJed Brown 12eb07d68fSJeremy L Thompson use crate::{ 13eb07d68fSJeremy L Thompson basis::{Basis, BasisOpt}, 14eb07d68fSJeremy L Thompson elem_restriction::{ElemRestriction, ElemRestrictionOpt}, 15eb07d68fSJeremy L Thompson prelude::*, 16eb07d68fSJeremy L Thompson qfunction::QFunctionOpt, 17eb07d68fSJeremy L Thompson vector::{Vector, VectorOpt}, 18eb07d68fSJeremy L Thompson }; 199df49d7eSJed Brown 209df49d7eSJed Brown // ----------------------------------------------------------------------------- 217ed177dbSJed Brown // Operator Field context wrapper 2208778c6fSJeremy L Thompson // ----------------------------------------------------------------------------- 2308778c6fSJeremy L Thompson #[derive(Debug)] 2408778c6fSJeremy L Thompson pub struct OperatorField<'a> { 2508778c6fSJeremy L Thompson pub(crate) ptr: bind_ceed::CeedOperatorField, 26e03fef56SJeremy L Thompson pub(crate) vector: crate::Vector<'a>, 27e03fef56SJeremy L Thompson pub(crate) elem_restriction: crate::ElemRestriction<'a>, 28e03fef56SJeremy L Thompson pub(crate) basis: crate::Basis<'a>, 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> { 362b671a0aSJeremy L Thompson pub(crate) unsafe fn from_raw( 37e03fef56SJeremy L Thompson ptr: bind_ceed::CeedOperatorField, 38e03fef56SJeremy L Thompson ceed: crate::Ceed, 39e03fef56SJeremy L Thompson ) -> crate::Result<Self> { 40e03fef56SJeremy L Thompson let vector = { 41e03fef56SJeremy L Thompson let mut vector_ptr = std::ptr::null_mut(); 422b671a0aSJeremy L Thompson ceed.check_error(bind_ceed::CeedOperatorFieldGetVector(ptr, &mut vector_ptr))?; 43e03fef56SJeremy L Thompson crate::Vector::from_raw(vector_ptr)? 44e03fef56SJeremy L Thompson }; 45e03fef56SJeremy L Thompson let elem_restriction = { 46e03fef56SJeremy L Thompson let mut elem_restriction_ptr = std::ptr::null_mut(); 472b671a0aSJeremy L Thompson ceed.check_error(bind_ceed::CeedOperatorFieldGetElemRestriction( 482b671a0aSJeremy L Thompson ptr, 492b671a0aSJeremy L Thompson &mut elem_restriction_ptr, 502b671a0aSJeremy L Thompson ))?; 51e03fef56SJeremy L Thompson crate::ElemRestriction::from_raw(elem_restriction_ptr)? 52e03fef56SJeremy L Thompson }; 53e03fef56SJeremy L Thompson let basis = { 54e03fef56SJeremy L Thompson let mut basis_ptr = std::ptr::null_mut(); 552b671a0aSJeremy L Thompson ceed.check_error(bind_ceed::CeedOperatorFieldGetBasis(ptr, &mut basis_ptr))?; 56e03fef56SJeremy L Thompson crate::Basis::from_raw(basis_ptr)? 57e03fef56SJeremy L Thompson }; 58e03fef56SJeremy L Thompson Ok(Self { 59e03fef56SJeremy L Thompson ptr, 60e03fef56SJeremy L Thompson vector, 61e03fef56SJeremy L Thompson elem_restriction, 62e03fef56SJeremy L Thompson basis, 63e03fef56SJeremy L Thompson _lifeline: PhantomData, 64e03fef56SJeremy L Thompson }) 65e03fef56SJeremy L Thompson } 66e03fef56SJeremy L Thompson 6708778c6fSJeremy L Thompson /// Get the name of an OperatorField 6808778c6fSJeremy L Thompson /// 6908778c6fSJeremy L Thompson /// ``` 70eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, MemType, QFunctionOpt, QuadMode, VectorOpt}; 714d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 7208778c6fSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 7308778c6fSJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 7408778c6fSJeremy L Thompson /// 7508778c6fSJeremy L Thompson /// // Operator field arguments 7608778c6fSJeremy L Thompson /// let ne = 3; 77bf55b007SJeremy L Thompson /// let q = 4_usize; 7808778c6fSJeremy L Thompson /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 7908778c6fSJeremy L Thompson /// for i in 0..ne { 8008778c6fSJeremy L Thompson /// ind[2 * i + 0] = i as i32; 8108778c6fSJeremy L Thompson /// ind[2 * i + 1] = (i + 1) as i32; 8208778c6fSJeremy L Thompson /// } 8308778c6fSJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 8408778c6fSJeremy L Thompson /// let strides: [i32; 3] = [1, q as i32, q as i32]; 85d9267b76SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 8608778c6fSJeremy L Thompson /// 8708778c6fSJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 8808778c6fSJeremy L Thompson /// 8908778c6fSJeremy L Thompson /// // Operator fields 9008778c6fSJeremy L Thompson /// let op = ceed 9108778c6fSJeremy L Thompson /// .operator(&qf, QFunctionOpt::None, QFunctionOpt::None)? 9208778c6fSJeremy L Thompson /// .field("dx", &r, &b, VectorOpt::Active)? 9308778c6fSJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &b, VectorOpt::None)? 94356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)?; 9508778c6fSJeremy L Thompson /// 9608778c6fSJeremy L Thompson /// let inputs = op.inputs()?; 9708778c6fSJeremy L Thompson /// 9808778c6fSJeremy L Thompson /// assert_eq!(inputs[0].name(), "dx", "Incorrect input name"); 9908778c6fSJeremy L Thompson /// assert_eq!(inputs[1].name(), "weights", "Incorrect input name"); 10008778c6fSJeremy L Thompson /// # Ok(()) 10108778c6fSJeremy L Thompson /// # } 10208778c6fSJeremy L Thompson /// ``` 10308778c6fSJeremy L Thompson pub fn name(&self) -> &str { 10408778c6fSJeremy L Thompson let mut name_ptr: *mut std::os::raw::c_char = std::ptr::null_mut(); 10508778c6fSJeremy L Thompson unsafe { 1066f8994e9SJeremy L Thompson bind_ceed::CeedOperatorFieldGetName( 1076f8994e9SJeremy L Thompson self.ptr, 1086f8994e9SJeremy L Thompson &mut name_ptr as *const _ as *mut *const _, 1096f8994e9SJeremy L Thompson ); 11008778c6fSJeremy L Thompson } 11108778c6fSJeremy L Thompson unsafe { CStr::from_ptr(name_ptr) }.to_str().unwrap() 11208778c6fSJeremy L Thompson } 11308778c6fSJeremy L Thompson 11408778c6fSJeremy L Thompson /// Get the ElemRestriction of an OperatorField 11508778c6fSJeremy L Thompson /// 11608778c6fSJeremy L Thompson /// ``` 117eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, MemType, QFunctionOpt, QuadMode, VectorOpt}; 1184d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 11908778c6fSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 12008778c6fSJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 12108778c6fSJeremy L Thompson /// 12208778c6fSJeremy L Thompson /// // Operator field arguments 12308778c6fSJeremy L Thompson /// let ne = 3; 124bf55b007SJeremy L Thompson /// let q = 4_usize; 12508778c6fSJeremy L Thompson /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 12608778c6fSJeremy L Thompson /// for i in 0..ne { 12708778c6fSJeremy L Thompson /// ind[2 * i + 0] = i as i32; 12808778c6fSJeremy L Thompson /// ind[2 * i + 1] = (i + 1) as i32; 12908778c6fSJeremy L Thompson /// } 13008778c6fSJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 13108778c6fSJeremy L Thompson /// let strides: [i32; 3] = [1, q as i32, q as i32]; 132d9267b76SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 13308778c6fSJeremy L Thompson /// 13408778c6fSJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 13508778c6fSJeremy L Thompson /// 13608778c6fSJeremy L Thompson /// // Operator fields 13708778c6fSJeremy L Thompson /// let op = ceed 13808778c6fSJeremy L Thompson /// .operator(&qf, QFunctionOpt::None, QFunctionOpt::None)? 13908778c6fSJeremy L Thompson /// .field("dx", &r, &b, VectorOpt::Active)? 14008778c6fSJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &b, VectorOpt::None)? 141356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)?; 14208778c6fSJeremy L Thompson /// 14308778c6fSJeremy L Thompson /// let inputs = op.inputs()?; 14408778c6fSJeremy L Thompson /// 14508778c6fSJeremy L Thompson /// assert!( 14608778c6fSJeremy L Thompson /// inputs[0].elem_restriction().is_some(), 14708778c6fSJeremy L Thompson /// "Incorrect field ElemRestriction" 14808778c6fSJeremy L Thompson /// ); 149567c3c29SJeremy L Thompson /// if let ElemRestrictionOpt::Some(r) = inputs[0].elem_restriction() { 150567c3c29SJeremy L Thompson /// assert_eq!( 151567c3c29SJeremy L Thompson /// r.num_elements(), 152567c3c29SJeremy L Thompson /// ne, 153567c3c29SJeremy L Thompson /// "Incorrect field ElemRestriction number of elements" 154567c3c29SJeremy L Thompson /// ); 155567c3c29SJeremy L Thompson /// } 156567c3c29SJeremy L Thompson /// 15708778c6fSJeremy L Thompson /// assert!( 15808778c6fSJeremy L Thompson /// inputs[1].elem_restriction().is_none(), 15908778c6fSJeremy L Thompson /// "Incorrect field ElemRestriction" 16008778c6fSJeremy L Thompson /// ); 161e03fef56SJeremy L Thompson /// 162e03fef56SJeremy L Thompson /// let outputs = op.outputs()?; 163e03fef56SJeremy L Thompson /// 164e03fef56SJeremy L Thompson /// assert!( 165e03fef56SJeremy L Thompson /// outputs[0].elem_restriction().is_some(), 166e03fef56SJeremy L Thompson /// "Incorrect field ElemRestriction" 167e03fef56SJeremy L Thompson /// ); 168567c3c29SJeremy L Thompson /// if let ElemRestrictionOpt::Some(r) = outputs[0].elem_restriction() { 169567c3c29SJeremy L Thompson /// assert_eq!( 170567c3c29SJeremy L Thompson /// r.num_elements(), 171567c3c29SJeremy L Thompson /// ne, 172567c3c29SJeremy L Thompson /// "Incorrect field ElemRestriction number of elements" 173567c3c29SJeremy L Thompson /// ); 174567c3c29SJeremy L Thompson /// } 17508778c6fSJeremy L Thompson /// # Ok(()) 17608778c6fSJeremy L Thompson /// # } 17708778c6fSJeremy L Thompson /// ``` 17808778c6fSJeremy L Thompson pub fn elem_restriction(&self) -> ElemRestrictionOpt { 179e03fef56SJeremy L Thompson if self.elem_restriction.ptr == unsafe { bind_ceed::CEED_ELEMRESTRICTION_NONE } { 18008778c6fSJeremy L Thompson ElemRestrictionOpt::None 18108778c6fSJeremy L Thompson } else { 182e03fef56SJeremy L Thompson ElemRestrictionOpt::Some(&self.elem_restriction) 18308778c6fSJeremy L Thompson } 18408778c6fSJeremy L Thompson } 18508778c6fSJeremy L Thompson 18608778c6fSJeremy L Thompson /// Get the Basis of an OperatorField 18708778c6fSJeremy L Thompson /// 18808778c6fSJeremy L Thompson /// ``` 189eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, MemType, QFunctionOpt, QuadMode, VectorOpt}; 1904d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 19108778c6fSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 19208778c6fSJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 19308778c6fSJeremy L Thompson /// 19408778c6fSJeremy L Thompson /// // Operator field arguments 19508778c6fSJeremy L Thompson /// let ne = 3; 196bf55b007SJeremy L Thompson /// let q = 4_usize; 19708778c6fSJeremy L Thompson /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 19808778c6fSJeremy L Thompson /// for i in 0..ne { 19908778c6fSJeremy L Thompson /// ind[2 * i + 0] = i as i32; 20008778c6fSJeremy L Thompson /// ind[2 * i + 1] = (i + 1) as i32; 20108778c6fSJeremy L Thompson /// } 20208778c6fSJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 20308778c6fSJeremy L Thompson /// let strides: [i32; 3] = [1, q as i32, q as i32]; 204d9267b76SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 20508778c6fSJeremy L Thompson /// 20608778c6fSJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 20708778c6fSJeremy L Thompson /// 20808778c6fSJeremy L Thompson /// // Operator fields 20908778c6fSJeremy L Thompson /// let op = ceed 21008778c6fSJeremy L Thompson /// .operator(&qf, QFunctionOpt::None, QFunctionOpt::None)? 21108778c6fSJeremy L Thompson /// .field("dx", &r, &b, VectorOpt::Active)? 21208778c6fSJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &b, VectorOpt::None)? 213356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)?; 21408778c6fSJeremy L Thompson /// 21508778c6fSJeremy L Thompson /// let inputs = op.inputs()?; 21608778c6fSJeremy L Thompson /// 21708778c6fSJeremy L Thompson /// assert!(inputs[0].basis().is_some(), "Incorrect field Basis"); 218567c3c29SJeremy L Thompson /// if let BasisOpt::Some(b) = inputs[0].basis() { 219567c3c29SJeremy L Thompson /// assert_eq!( 220567c3c29SJeremy L Thompson /// b.num_quadrature_points(), 221567c3c29SJeremy L Thompson /// q, 222567c3c29SJeremy L Thompson /// "Incorrect field Basis number of quadrature points" 223567c3c29SJeremy L Thompson /// ); 224567c3c29SJeremy L Thompson /// } 22508778c6fSJeremy L Thompson /// assert!(inputs[1].basis().is_some(), "Incorrect field Basis"); 226567c3c29SJeremy L Thompson /// if let BasisOpt::Some(b) = inputs[1].basis() { 227567c3c29SJeremy L Thompson /// assert_eq!( 228567c3c29SJeremy L Thompson /// b.num_quadrature_points(), 229567c3c29SJeremy L Thompson /// q, 230567c3c29SJeremy L Thompson /// "Incorrect field Basis number of quadrature points" 231567c3c29SJeremy L Thompson /// ); 232567c3c29SJeremy L Thompson /// } 23308778c6fSJeremy L Thompson /// 23408778c6fSJeremy L Thompson /// let outputs = op.outputs()?; 23508778c6fSJeremy L Thompson /// 236356036faSJeremy L Thompson /// assert!(outputs[0].basis().is_none(), "Incorrect field Basis"); 23708778c6fSJeremy L Thompson /// # Ok(()) 23808778c6fSJeremy L Thompson /// # } 23908778c6fSJeremy L Thompson /// ``` 24008778c6fSJeremy L Thompson pub fn basis(&self) -> BasisOpt { 241e03fef56SJeremy L Thompson if self.basis.ptr == unsafe { bind_ceed::CEED_BASIS_NONE } { 242356036faSJeremy L Thompson BasisOpt::None 24308778c6fSJeremy L Thompson } else { 244e03fef56SJeremy L Thompson BasisOpt::Some(&self.basis) 24508778c6fSJeremy L Thompson } 24608778c6fSJeremy L Thompson } 24708778c6fSJeremy L Thompson 24808778c6fSJeremy L Thompson /// Get the Vector of an OperatorField 24908778c6fSJeremy L Thompson /// 25008778c6fSJeremy L Thompson /// ``` 251eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, MemType, QFunctionOpt, QuadMode, VectorOpt}; 2524d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 25308778c6fSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 25408778c6fSJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 25508778c6fSJeremy L Thompson /// 25608778c6fSJeremy L Thompson /// // Operator field arguments 25708778c6fSJeremy L Thompson /// let ne = 3; 258bf55b007SJeremy L Thompson /// let q = 4_usize; 25908778c6fSJeremy L Thompson /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 26008778c6fSJeremy L Thompson /// for i in 0..ne { 26108778c6fSJeremy L Thompson /// ind[2 * i + 0] = i as i32; 26208778c6fSJeremy L Thompson /// ind[2 * i + 1] = (i + 1) as i32; 26308778c6fSJeremy L Thompson /// } 26408778c6fSJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 26508778c6fSJeremy L Thompson /// let strides: [i32; 3] = [1, q as i32, q as i32]; 266d9267b76SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 26708778c6fSJeremy L Thompson /// 26808778c6fSJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 26908778c6fSJeremy L Thompson /// 27008778c6fSJeremy L Thompson /// // Operator fields 27108778c6fSJeremy L Thompson /// let op = ceed 27208778c6fSJeremy L Thompson /// .operator(&qf, QFunctionOpt::None, QFunctionOpt::None)? 27308778c6fSJeremy L Thompson /// .field("dx", &r, &b, VectorOpt::Active)? 27408778c6fSJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &b, VectorOpt::None)? 275356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)?; 27608778c6fSJeremy L Thompson /// 27708778c6fSJeremy L Thompson /// let inputs = op.inputs()?; 27808778c6fSJeremy L Thompson /// 27908778c6fSJeremy L Thompson /// assert!(inputs[0].vector().is_active(), "Incorrect field Vector"); 28008778c6fSJeremy L Thompson /// assert!(inputs[1].vector().is_none(), "Incorrect field Vector"); 281e03fef56SJeremy L Thompson /// 282e03fef56SJeremy L Thompson /// let outputs = op.outputs()?; 283e03fef56SJeremy L Thompson /// 284e03fef56SJeremy L Thompson /// assert!(outputs[0].vector().is_active(), "Incorrect field Vector"); 28508778c6fSJeremy L Thompson /// # Ok(()) 28608778c6fSJeremy L Thompson /// # } 28708778c6fSJeremy L Thompson /// ``` 28808778c6fSJeremy L Thompson pub fn vector(&self) -> VectorOpt { 289e03fef56SJeremy L Thompson if self.vector.ptr == unsafe { bind_ceed::CEED_VECTOR_ACTIVE } { 29008778c6fSJeremy L Thompson VectorOpt::Active 291e03fef56SJeremy L Thompson } else if self.vector.ptr == unsafe { bind_ceed::CEED_VECTOR_NONE } { 29208778c6fSJeremy L Thompson VectorOpt::None 29308778c6fSJeremy L Thompson } else { 294e03fef56SJeremy L Thompson VectorOpt::Some(&self.vector) 29508778c6fSJeremy L Thompson } 29608778c6fSJeremy L Thompson } 29708778c6fSJeremy L Thompson } 29808778c6fSJeremy L Thompson 29908778c6fSJeremy L Thompson // ----------------------------------------------------------------------------- 3007ed177dbSJed Brown // Operator context wrapper 3019df49d7eSJed Brown // ----------------------------------------------------------------------------- 302c68be7a2SJeremy L Thompson #[derive(Debug)] 3039df49d7eSJed Brown pub(crate) struct OperatorCore<'a> { 3049df49d7eSJed Brown ptr: bind_ceed::CeedOperator, 3051142270cSJeremy L Thompson _lifeline: PhantomData<&'a ()>, 3069df49d7eSJed Brown } 3079df49d7eSJed Brown 308c68be7a2SJeremy L Thompson #[derive(Debug)] 3099df49d7eSJed Brown pub struct Operator<'a> { 3109df49d7eSJed Brown op_core: OperatorCore<'a>, 3119df49d7eSJed Brown } 3129df49d7eSJed Brown 313c68be7a2SJeremy L Thompson #[derive(Debug)] 3149df49d7eSJed Brown pub struct CompositeOperator<'a> { 3159df49d7eSJed Brown op_core: OperatorCore<'a>, 3169df49d7eSJed Brown } 3179df49d7eSJed Brown 3189df49d7eSJed Brown // ----------------------------------------------------------------------------- 3199df49d7eSJed Brown // Destructor 3209df49d7eSJed Brown // ----------------------------------------------------------------------------- 3219df49d7eSJed Brown impl<'a> Drop for OperatorCore<'a> { 3229df49d7eSJed Brown fn drop(&mut self) { 3239df49d7eSJed Brown unsafe { 3249df49d7eSJed Brown bind_ceed::CeedOperatorDestroy(&mut self.ptr); 3259df49d7eSJed Brown } 3269df49d7eSJed Brown } 3279df49d7eSJed Brown } 3289df49d7eSJed Brown 3299df49d7eSJed Brown // ----------------------------------------------------------------------------- 3309df49d7eSJed Brown // Display 3319df49d7eSJed Brown // ----------------------------------------------------------------------------- 3329df49d7eSJed Brown impl<'a> fmt::Display for OperatorCore<'a> { 3339df49d7eSJed Brown fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 3349df49d7eSJed Brown let mut ptr = std::ptr::null_mut(); 3359df49d7eSJed Brown let mut sizeloc = crate::MAX_BUFFER_LENGTH; 3369df49d7eSJed Brown let cstring = unsafe { 3379df49d7eSJed Brown let file = bind_ceed::open_memstream(&mut ptr, &mut sizeloc); 3389df49d7eSJed Brown bind_ceed::CeedOperatorView(self.ptr, file); 3399df49d7eSJed Brown bind_ceed::fclose(file); 3409df49d7eSJed Brown CString::from_raw(ptr) 3419df49d7eSJed Brown }; 3429df49d7eSJed Brown cstring.to_string_lossy().fmt(f) 3439df49d7eSJed Brown } 3449df49d7eSJed Brown } 3459df49d7eSJed Brown 3469df49d7eSJed Brown /// View an Operator 3479df49d7eSJed Brown /// 3489df49d7eSJed Brown /// ``` 349eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, MemType, QFunctionOpt, QuadMode, VectorOpt}; 3504d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 3519df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 352c68be7a2SJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 3539df49d7eSJed Brown /// 3549df49d7eSJed Brown /// // Operator field arguments 3559df49d7eSJed Brown /// let ne = 3; 356bf55b007SJeremy L Thompson /// let q = 4_usize; 3579df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 3589df49d7eSJed Brown /// for i in 0..ne { 3599df49d7eSJed Brown /// ind[2 * i + 0] = i as i32; 3609df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32; 3619df49d7eSJed Brown /// } 362c68be7a2SJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 3639df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 364d9267b76SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 3659df49d7eSJed Brown /// 366c68be7a2SJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 3679df49d7eSJed Brown /// 3689df49d7eSJed Brown /// // Operator fields 3699df49d7eSJed Brown /// let op = ceed 370c68be7a2SJeremy L Thompson /// .operator(&qf, QFunctionOpt::None, QFunctionOpt::None)? 371ea6b5821SJeremy L Thompson /// .name("mass")? 372c68be7a2SJeremy L Thompson /// .field("dx", &r, &b, VectorOpt::Active)? 373c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &b, VectorOpt::None)? 374356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)?; 3759df49d7eSJed Brown /// 3769df49d7eSJed Brown /// println!("{}", op); 377c68be7a2SJeremy L Thompson /// # Ok(()) 378c68be7a2SJeremy L Thompson /// # } 3799df49d7eSJed Brown /// ``` 3809df49d7eSJed Brown impl<'a> fmt::Display for Operator<'a> { 3819df49d7eSJed Brown fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 3829df49d7eSJed Brown self.op_core.fmt(f) 3839df49d7eSJed Brown } 3849df49d7eSJed Brown } 3859df49d7eSJed Brown 3869df49d7eSJed Brown /// View a composite Operator 3879df49d7eSJed Brown /// 3889df49d7eSJed Brown /// ``` 389eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, MemType, QFunctionOpt, QuadMode, VectorOpt}; 3904d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 3919df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 3929df49d7eSJed Brown /// 3939df49d7eSJed Brown /// // Sub operator field arguments 3949df49d7eSJed Brown /// let ne = 3; 395bf55b007SJeremy L Thompson /// let q = 4_usize; 3969df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 3979df49d7eSJed Brown /// for i in 0..ne { 3989df49d7eSJed Brown /// ind[2 * i + 0] = i as i32; 3999df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32; 4009df49d7eSJed Brown /// } 401c68be7a2SJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 4029df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 403d9267b76SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 4049df49d7eSJed Brown /// 405c68be7a2SJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 4069df49d7eSJed Brown /// 407c68be7a2SJeremy L Thompson /// let qdata_mass = ceed.vector(q * ne)?; 408c68be7a2SJeremy L Thompson /// let qdata_diff = ceed.vector(q * ne)?; 4099df49d7eSJed Brown /// 410c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 4119df49d7eSJed Brown /// let op_mass = ceed 412c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 413ea6b5821SJeremy L Thompson /// .name("Mass term")? 414c68be7a2SJeremy L Thompson /// .field("u", &r, &b, VectorOpt::Active)? 415356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, &qdata_mass)? 416c68be7a2SJeremy L Thompson /// .field("v", &r, &b, VectorOpt::Active)?; 4179df49d7eSJed Brown /// 418c68be7a2SJeremy L Thompson /// let qf_diff = ceed.q_function_interior_by_name("Poisson1DApply")?; 4199df49d7eSJed Brown /// let op_diff = ceed 420c68be7a2SJeremy L Thompson /// .operator(&qf_diff, QFunctionOpt::None, QFunctionOpt::None)? 421ea6b5821SJeremy L Thompson /// .name("Poisson term")? 422c68be7a2SJeremy L Thompson /// .field("du", &r, &b, VectorOpt::Active)? 423356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, &qdata_diff)? 424c68be7a2SJeremy L Thompson /// .field("dv", &r, &b, VectorOpt::Active)?; 4259df49d7eSJed Brown /// 4269df49d7eSJed Brown /// let op = ceed 427c68be7a2SJeremy L Thompson /// .composite_operator()? 428ea6b5821SJeremy L Thompson /// .name("Screened Poisson")? 429c68be7a2SJeremy L Thompson /// .sub_operator(&op_mass)? 430c68be7a2SJeremy L Thompson /// .sub_operator(&op_diff)?; 4319df49d7eSJed Brown /// 4329df49d7eSJed Brown /// println!("{}", op); 433c68be7a2SJeremy L Thompson /// # Ok(()) 434c68be7a2SJeremy L Thompson /// # } 4359df49d7eSJed Brown /// ``` 4369df49d7eSJed Brown impl<'a> fmt::Display for CompositeOperator<'a> { 4379df49d7eSJed Brown fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 4389df49d7eSJed Brown self.op_core.fmt(f) 4399df49d7eSJed Brown } 4409df49d7eSJed Brown } 4419df49d7eSJed Brown 4429df49d7eSJed Brown // ----------------------------------------------------------------------------- 4439df49d7eSJed Brown // Core functionality 4449df49d7eSJed Brown // ----------------------------------------------------------------------------- 4459df49d7eSJed Brown impl<'a> OperatorCore<'a> { 44611544396SJeremy L Thompson // Raw Ceed for error handling 44711544396SJeremy L Thompson #[doc(hidden)] 44811544396SJeremy L Thompson fn ceed(&self) -> bind_ceed::Ceed { 44911544396SJeremy L Thompson unsafe { bind_ceed::CeedOperatorReturnCeed(self.ptr) } 45011544396SJeremy L Thompson } 45111544396SJeremy L Thompson 4521142270cSJeremy L Thompson // Error handling 4531142270cSJeremy L Thompson #[doc(hidden)] 4541142270cSJeremy L Thompson fn check_error(&self, ierr: i32) -> crate::Result<i32> { 45511544396SJeremy L Thompson crate::check_error(|| self.ceed(), ierr) 4561142270cSJeremy L Thompson } 4571142270cSJeremy L Thompson 4589df49d7eSJed Brown // Common implementations 4596f97ff0aSJeremy L Thompson pub fn check(&self) -> crate::Result<i32> { 460656ef1e5SJeremy L Thompson self.check_error(unsafe { bind_ceed::CeedOperatorCheckReady(self.ptr) }) 4616f97ff0aSJeremy L Thompson } 4626f97ff0aSJeremy L Thompson 463ea6b5821SJeremy L Thompson pub fn name(&self, name: &str) -> crate::Result<i32> { 464ea6b5821SJeremy L Thompson let name_c = CString::new(name).expect("CString::new failed"); 465656ef1e5SJeremy L Thompson self.check_error(unsafe { bind_ceed::CeedOperatorSetName(self.ptr, name_c.as_ptr()) }) 466ea6b5821SJeremy L Thompson } 467ea6b5821SJeremy L Thompson 4689df49d7eSJed Brown pub fn apply(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> { 469656ef1e5SJeremy L Thompson self.check_error(unsafe { 4709df49d7eSJed Brown bind_ceed::CeedOperatorApply( 4719df49d7eSJed Brown self.ptr, 4729df49d7eSJed Brown input.ptr, 4739df49d7eSJed Brown output.ptr, 4749df49d7eSJed Brown bind_ceed::CEED_REQUEST_IMMEDIATE, 4759df49d7eSJed Brown ) 476656ef1e5SJeremy L Thompson }) 4779df49d7eSJed Brown } 4789df49d7eSJed Brown 4799df49d7eSJed Brown pub fn apply_add(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> { 480656ef1e5SJeremy L Thompson self.check_error(unsafe { 4819df49d7eSJed Brown bind_ceed::CeedOperatorApplyAdd( 4829df49d7eSJed Brown self.ptr, 4839df49d7eSJed Brown input.ptr, 4849df49d7eSJed Brown output.ptr, 4859df49d7eSJed Brown bind_ceed::CEED_REQUEST_IMMEDIATE, 4869df49d7eSJed Brown ) 487656ef1e5SJeremy L Thompson }) 4889df49d7eSJed Brown } 4899df49d7eSJed Brown 4909df49d7eSJed Brown pub fn linear_assemble_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> { 491656ef1e5SJeremy L Thompson self.check_error(unsafe { 4929df49d7eSJed Brown bind_ceed::CeedOperatorLinearAssembleDiagonal( 4939df49d7eSJed Brown self.ptr, 4949df49d7eSJed Brown assembled.ptr, 4959df49d7eSJed Brown bind_ceed::CEED_REQUEST_IMMEDIATE, 4969df49d7eSJed Brown ) 497656ef1e5SJeremy L Thompson }) 4989df49d7eSJed Brown } 4999df49d7eSJed Brown 5009df49d7eSJed Brown pub fn linear_assemble_add_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> { 501656ef1e5SJeremy L Thompson self.check_error(unsafe { 5029df49d7eSJed Brown bind_ceed::CeedOperatorLinearAssembleAddDiagonal( 5039df49d7eSJed Brown self.ptr, 5049df49d7eSJed Brown assembled.ptr, 5059df49d7eSJed Brown bind_ceed::CEED_REQUEST_IMMEDIATE, 5069df49d7eSJed Brown ) 507656ef1e5SJeremy L Thompson }) 5089df49d7eSJed Brown } 5099df49d7eSJed Brown 5109df49d7eSJed Brown pub fn linear_assemble_point_block_diagonal( 5119df49d7eSJed Brown &self, 5129df49d7eSJed Brown assembled: &mut Vector, 5139df49d7eSJed Brown ) -> crate::Result<i32> { 514656ef1e5SJeremy L Thompson self.check_error(unsafe { 5159df49d7eSJed Brown bind_ceed::CeedOperatorLinearAssemblePointBlockDiagonal( 5169df49d7eSJed Brown self.ptr, 5179df49d7eSJed Brown assembled.ptr, 5189df49d7eSJed Brown bind_ceed::CEED_REQUEST_IMMEDIATE, 5199df49d7eSJed Brown ) 520656ef1e5SJeremy L Thompson }) 5219df49d7eSJed Brown } 5229df49d7eSJed Brown 5239df49d7eSJed Brown pub fn linear_assemble_add_point_block_diagonal( 5249df49d7eSJed Brown &self, 5259df49d7eSJed Brown assembled: &mut Vector, 5269df49d7eSJed Brown ) -> crate::Result<i32> { 527656ef1e5SJeremy L Thompson self.check_error(unsafe { 5289df49d7eSJed Brown bind_ceed::CeedOperatorLinearAssembleAddPointBlockDiagonal( 5299df49d7eSJed Brown self.ptr, 5309df49d7eSJed Brown assembled.ptr, 5319df49d7eSJed Brown bind_ceed::CEED_REQUEST_IMMEDIATE, 5329df49d7eSJed Brown ) 533656ef1e5SJeremy L Thompson }) 5349df49d7eSJed Brown } 5359df49d7eSJed Brown } 5369df49d7eSJed Brown 5379df49d7eSJed Brown // ----------------------------------------------------------------------------- 5389df49d7eSJed Brown // Operator 5399df49d7eSJed Brown // ----------------------------------------------------------------------------- 5409df49d7eSJed Brown impl<'a> Operator<'a> { 5419df49d7eSJed Brown // Constructor 5429df49d7eSJed Brown pub fn create<'b>( 543594ef120SJeremy L Thompson ceed: &crate::Ceed, 5449df49d7eSJed Brown qf: impl Into<QFunctionOpt<'b>>, 5459df49d7eSJed Brown dqf: impl Into<QFunctionOpt<'b>>, 5469df49d7eSJed Brown dqfT: impl Into<QFunctionOpt<'b>>, 5479df49d7eSJed Brown ) -> crate::Result<Self> { 5489df49d7eSJed Brown let mut ptr = std::ptr::null_mut(); 549656ef1e5SJeremy L Thompson ceed.check_error(unsafe { 5509df49d7eSJed Brown bind_ceed::CeedOperatorCreate( 5519df49d7eSJed Brown ceed.ptr, 5529df49d7eSJed Brown qf.into().to_raw(), 5539df49d7eSJed Brown dqf.into().to_raw(), 5549df49d7eSJed Brown dqfT.into().to_raw(), 5559df49d7eSJed Brown &mut ptr, 5569df49d7eSJed Brown ) 557656ef1e5SJeremy L Thompson })?; 5589df49d7eSJed Brown Ok(Self { 5591142270cSJeremy L Thompson op_core: OperatorCore { 5601142270cSJeremy L Thompson ptr, 5611142270cSJeremy L Thompson _lifeline: PhantomData, 5621142270cSJeremy L Thompson }, 5639df49d7eSJed Brown }) 5649df49d7eSJed Brown } 5659df49d7eSJed Brown 5662b671a0aSJeremy L Thompson unsafe fn from_raw(ptr: bind_ceed::CeedOperator) -> crate::Result<Self> { 5679df49d7eSJed Brown Ok(Self { 5681142270cSJeremy L Thompson op_core: OperatorCore { 5691142270cSJeremy L Thompson ptr, 5701142270cSJeremy L Thompson _lifeline: PhantomData, 5711142270cSJeremy L Thompson }, 5729df49d7eSJed Brown }) 5739df49d7eSJed Brown } 5749df49d7eSJed Brown 575ea6b5821SJeremy L Thompson /// Set name for Operator printing 576ea6b5821SJeremy L Thompson /// 577ea6b5821SJeremy L Thompson /// * 'name' - Name to set 578ea6b5821SJeremy L Thompson /// 579ea6b5821SJeremy L Thompson /// ``` 580eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, MemType, QFunctionOpt, QuadMode, VectorOpt}; 581ea6b5821SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 582ea6b5821SJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 583ea6b5821SJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 584ea6b5821SJeremy L Thompson /// 585ea6b5821SJeremy L Thompson /// // Operator field arguments 586ea6b5821SJeremy L Thompson /// let ne = 3; 587bf55b007SJeremy L Thompson /// let q = 4_usize; 588ea6b5821SJeremy L Thompson /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 589ea6b5821SJeremy L Thompson /// for i in 0..ne { 590ea6b5821SJeremy L Thompson /// ind[2 * i + 0] = i as i32; 591ea6b5821SJeremy L Thompson /// ind[2 * i + 1] = (i + 1) as i32; 592ea6b5821SJeremy L Thompson /// } 593ea6b5821SJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 594ea6b5821SJeremy L Thompson /// let strides: [i32; 3] = [1, q as i32, q as i32]; 595d9267b76SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 596ea6b5821SJeremy L Thompson /// 597ea6b5821SJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 598ea6b5821SJeremy L Thompson /// 599ea6b5821SJeremy L Thompson /// // Operator fields 600ea6b5821SJeremy L Thompson /// let op = ceed 601ea6b5821SJeremy L Thompson /// .operator(&qf, QFunctionOpt::None, QFunctionOpt::None)? 602ea6b5821SJeremy L Thompson /// .name("mass")? 603ea6b5821SJeremy L Thompson /// .field("dx", &r, &b, VectorOpt::Active)? 604ea6b5821SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &b, VectorOpt::None)? 605356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)?; 606ea6b5821SJeremy L Thompson /// # Ok(()) 607ea6b5821SJeremy L Thompson /// # } 608ea6b5821SJeremy L Thompson /// ``` 609ea6b5821SJeremy L Thompson #[allow(unused_mut)] 610ea6b5821SJeremy L Thompson pub fn name(mut self, name: &str) -> crate::Result<Self> { 611ea6b5821SJeremy L Thompson self.op_core.name(name)?; 612ea6b5821SJeremy L Thompson Ok(self) 613ea6b5821SJeremy L Thompson } 614ea6b5821SJeremy L Thompson 6159df49d7eSJed Brown /// Apply Operator to a vector 6169df49d7eSJed Brown /// 6179df49d7eSJed Brown /// * `input` - Input Vector 6189df49d7eSJed Brown /// * `output` - Output Vector 6199df49d7eSJed Brown /// 6209df49d7eSJed Brown /// ``` 621eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, MemType, QFunctionOpt, QuadMode, Scalar, VectorOpt}; 6224d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 6239df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 6249df49d7eSJed Brown /// let ne = 4; 6259df49d7eSJed Brown /// let p = 3; 6269df49d7eSJed Brown /// let q = 4; 6279df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 6289df49d7eSJed Brown /// 6299df49d7eSJed Brown /// // Vectors 630c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0])?; 631c68be7a2SJeremy L Thompson /// let mut qdata = ceed.vector(ne * q)?; 6329df49d7eSJed Brown /// qdata.set_value(0.0); 633c68be7a2SJeremy L Thompson /// let u = ceed.vector_from_slice(&vec![1.0; ndofs])?; 634c68be7a2SJeremy L Thompson /// let mut v = ceed.vector(ndofs)?; 6359df49d7eSJed Brown /// v.set_value(0.0); 6369df49d7eSJed Brown /// 6379df49d7eSJed Brown /// // Restrictions 6389df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 6399df49d7eSJed Brown /// for i in 0..ne { 6409df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 6419df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 6429df49d7eSJed Brown /// } 643c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 6449df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 6459df49d7eSJed Brown /// for i in 0..ne { 6469df49d7eSJed Brown /// indu[p * i + 0] = i as i32; 6479df49d7eSJed Brown /// indu[p * i + 1] = (i + 1) as i32; 6489df49d7eSJed Brown /// indu[p * i + 2] = (i + 2) as i32; 6499df49d7eSJed Brown /// } 650c68be7a2SJeremy L Thompson /// let ru = ceed.elem_restriction(ne, 3, 1, 1, ndofs, MemType::Host, &indu)?; 6519df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 652c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 6539df49d7eSJed Brown /// 6549df49d7eSJed Brown /// // Bases 655c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 656c68be7a2SJeremy L Thompson /// let bu = ceed.basis_tensor_H1_Lagrange(1, 1, p, q, QuadMode::Gauss)?; 6579df49d7eSJed Brown /// 6589df49d7eSJed Brown /// // Build quadrature data 659c68be7a2SJeremy L Thompson /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 660c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 661c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 662c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 663356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)? 664c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata)?; 6659df49d7eSJed Brown /// 6669df49d7eSJed Brown /// // Mass operator 667c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 6689df49d7eSJed Brown /// let op_mass = ceed 669c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 670c68be7a2SJeremy L Thompson /// .field("u", &ru, &bu, VectorOpt::Active)? 671356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, &qdata)? 672c68be7a2SJeremy L Thompson /// .field("v", &ru, &bu, VectorOpt::Active)?; 6739df49d7eSJed Brown /// 6749df49d7eSJed Brown /// v.set_value(0.0); 675c68be7a2SJeremy L Thompson /// op_mass.apply(&u, &mut v)?; 6769df49d7eSJed Brown /// 6779df49d7eSJed Brown /// // Check 678e78171edSJeremy L Thompson /// let sum: Scalar = v.view()?.iter().sum(); 6794b61a5a0SRezgar Shakeri /// let error: Scalar = (sum - 2.0).abs(); 6809df49d7eSJed Brown /// assert!( 6814b61a5a0SRezgar Shakeri /// error < 50.0 * libceed::EPSILON, 6824b61a5a0SRezgar Shakeri /// "Incorrect interval length computed. Expected: 2.0, Found: {}, Error: {:.12e}", 6834b61a5a0SRezgar Shakeri /// sum, 6844b61a5a0SRezgar Shakeri /// error 6859df49d7eSJed Brown /// ); 686c68be7a2SJeremy L Thompson /// # Ok(()) 687c68be7a2SJeremy L Thompson /// # } 6889df49d7eSJed Brown /// ``` 6899df49d7eSJed Brown pub fn apply(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> { 6909df49d7eSJed Brown self.op_core.apply(input, output) 6919df49d7eSJed Brown } 6929df49d7eSJed Brown 6939df49d7eSJed Brown /// Apply Operator to a vector and add result to output vector 6949df49d7eSJed Brown /// 6959df49d7eSJed Brown /// * `input` - Input Vector 6969df49d7eSJed Brown /// * `output` - Output Vector 6979df49d7eSJed Brown /// 6989df49d7eSJed Brown /// ``` 699eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, MemType, QFunctionOpt, QuadMode, Scalar, VectorOpt}; 7004d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 7019df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 7029df49d7eSJed Brown /// let ne = 4; 7039df49d7eSJed Brown /// let p = 3; 7049df49d7eSJed Brown /// let q = 4; 7059df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 7069df49d7eSJed Brown /// 7079df49d7eSJed Brown /// // Vectors 708c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0])?; 709c68be7a2SJeremy L Thompson /// let mut qdata = ceed.vector(ne * q)?; 7109df49d7eSJed Brown /// qdata.set_value(0.0); 711c68be7a2SJeremy L Thompson /// let u = ceed.vector_from_slice(&vec![1.0; ndofs])?; 712c68be7a2SJeremy L Thompson /// let mut v = ceed.vector(ndofs)?; 7139df49d7eSJed Brown /// 7149df49d7eSJed Brown /// // Restrictions 7159df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 7169df49d7eSJed Brown /// for i in 0..ne { 7179df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 7189df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 7199df49d7eSJed Brown /// } 720c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 7219df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 7229df49d7eSJed Brown /// for i in 0..ne { 7239df49d7eSJed Brown /// indu[p * i + 0] = i as i32; 7249df49d7eSJed Brown /// indu[p * i + 1] = (i + 1) as i32; 7259df49d7eSJed Brown /// indu[p * i + 2] = (i + 2) as i32; 7269df49d7eSJed Brown /// } 727c68be7a2SJeremy L Thompson /// let ru = ceed.elem_restriction(ne, 3, 1, 1, ndofs, MemType::Host, &indu)?; 7289df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 729c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 7309df49d7eSJed Brown /// 7319df49d7eSJed Brown /// // Bases 732c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 733c68be7a2SJeremy L Thompson /// let bu = ceed.basis_tensor_H1_Lagrange(1, 1, p, q, QuadMode::Gauss)?; 7349df49d7eSJed Brown /// 7359df49d7eSJed Brown /// // Build quadrature data 736c68be7a2SJeremy L Thompson /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 737c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 738c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 739c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 740356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)? 741c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata)?; 7429df49d7eSJed Brown /// 7439df49d7eSJed Brown /// // Mass operator 744c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 7459df49d7eSJed Brown /// let op_mass = ceed 746c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 747c68be7a2SJeremy L Thompson /// .field("u", &ru, &bu, VectorOpt::Active)? 748356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, &qdata)? 749c68be7a2SJeremy L Thompson /// .field("v", &ru, &bu, VectorOpt::Active)?; 7509df49d7eSJed Brown /// 7519df49d7eSJed Brown /// v.set_value(1.0); 752c68be7a2SJeremy L Thompson /// op_mass.apply_add(&u, &mut v)?; 7539df49d7eSJed Brown /// 7549df49d7eSJed Brown /// // Check 755e78171edSJeremy L Thompson /// let sum: Scalar = v.view()?.iter().sum(); 7569df49d7eSJed Brown /// assert!( 75780a9ef05SNatalie Beams /// (sum - (2.0 + ndofs as Scalar)).abs() < 10.0 * libceed::EPSILON, 7589df49d7eSJed Brown /// "Incorrect interval length computed and added" 7599df49d7eSJed Brown /// ); 760c68be7a2SJeremy L Thompson /// # Ok(()) 761c68be7a2SJeremy L Thompson /// # } 7629df49d7eSJed Brown /// ``` 7639df49d7eSJed Brown pub fn apply_add(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> { 7649df49d7eSJed Brown self.op_core.apply_add(input, output) 7659df49d7eSJed Brown } 7669df49d7eSJed Brown 7679df49d7eSJed Brown /// Provide a field to a Operator for use by its QFunction 7689df49d7eSJed Brown /// 7699df49d7eSJed Brown /// * `fieldname` - Name of the field (to be matched with the name used by 7709df49d7eSJed Brown /// the QFunction) 7719df49d7eSJed Brown /// * `r` - ElemRestriction 772356036faSJeremy L Thompson /// * `b` - Basis in which the field resides or `BasisOpt::None` 773356036faSJeremy L Thompson /// * `v` - Vector to be used by Operator or `VectorOpt::Active` if field 774356036faSJeremy L Thompson /// is active or `VectorOpt::None` if using `Weight` with the 7759df49d7eSJed Brown /// QFunction 7769df49d7eSJed Brown /// 7779df49d7eSJed Brown /// 7789df49d7eSJed Brown /// ``` 779eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, MemType, QFunctionOpt, QuadMode, VectorOpt}; 7804d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 7819df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 782c68be7a2SJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 783c68be7a2SJeremy L Thompson /// let mut op = ceed.operator(&qf, QFunctionOpt::None, QFunctionOpt::None)?; 7849df49d7eSJed Brown /// 7859df49d7eSJed Brown /// // Operator field arguments 7869df49d7eSJed Brown /// let ne = 3; 7879df49d7eSJed Brown /// let q = 4; 7889df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 7899df49d7eSJed Brown /// for i in 0..ne { 7909df49d7eSJed Brown /// ind[2 * i + 0] = i as i32; 7919df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32; 7929df49d7eSJed Brown /// } 793c68be7a2SJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 7949df49d7eSJed Brown /// 795c68be7a2SJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 7969df49d7eSJed Brown /// 7979df49d7eSJed Brown /// // Operator field 798c68be7a2SJeremy L Thompson /// op = op.field("dx", &r, &b, VectorOpt::Active)?; 799c68be7a2SJeremy L Thompson /// # Ok(()) 800c68be7a2SJeremy L Thompson /// # } 8019df49d7eSJed Brown /// ``` 8029df49d7eSJed Brown #[allow(unused_mut)] 8039df49d7eSJed Brown pub fn field<'b>( 8049df49d7eSJed Brown mut self, 8059df49d7eSJed Brown fieldname: &str, 8069df49d7eSJed Brown r: impl Into<ElemRestrictionOpt<'b>>, 8079df49d7eSJed Brown b: impl Into<BasisOpt<'b>>, 8089df49d7eSJed Brown v: impl Into<VectorOpt<'b>>, 8099df49d7eSJed Brown ) -> crate::Result<Self> { 8109df49d7eSJed Brown let fieldname = CString::new(fieldname).expect("CString::new failed"); 811bf55b007SJeremy L Thompson let fieldname = fieldname.as_ptr(); 812656ef1e5SJeremy L Thompson self.op_core.check_error(unsafe { 8139df49d7eSJed Brown bind_ceed::CeedOperatorSetField( 8149df49d7eSJed Brown self.op_core.ptr, 8159df49d7eSJed Brown fieldname, 8169df49d7eSJed Brown r.into().to_raw(), 8179df49d7eSJed Brown b.into().to_raw(), 8189df49d7eSJed Brown v.into().to_raw(), 8199df49d7eSJed Brown ) 820656ef1e5SJeremy L Thompson })?; 8219df49d7eSJed Brown Ok(self) 8229df49d7eSJed Brown } 8239df49d7eSJed Brown 82408778c6fSJeremy L Thompson /// Get a slice of Operator inputs 82508778c6fSJeremy L Thompson /// 82608778c6fSJeremy L Thompson /// ``` 827eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, MemType, QFunctionOpt, QuadMode, Scalar, VectorOpt}; 8284d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 82908778c6fSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 83008778c6fSJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 83108778c6fSJeremy L Thompson /// 83208778c6fSJeremy L Thompson /// // Operator field arguments 83308778c6fSJeremy L Thompson /// let ne = 3; 834bf55b007SJeremy L Thompson /// let q = 4_usize; 83508778c6fSJeremy L Thompson /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 83608778c6fSJeremy L Thompson /// for i in 0..ne { 83708778c6fSJeremy L Thompson /// ind[2 * i + 0] = i as i32; 83808778c6fSJeremy L Thompson /// ind[2 * i + 1] = (i + 1) as i32; 83908778c6fSJeremy L Thompson /// } 84008778c6fSJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 84108778c6fSJeremy L Thompson /// let strides: [i32; 3] = [1, q as i32, q as i32]; 842d9267b76SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 84308778c6fSJeremy L Thompson /// 84408778c6fSJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 84508778c6fSJeremy L Thompson /// 84608778c6fSJeremy L Thompson /// // Operator fields 84708778c6fSJeremy L Thompson /// let op = ceed 84808778c6fSJeremy L Thompson /// .operator(&qf, QFunctionOpt::None, QFunctionOpt::None)? 84908778c6fSJeremy L Thompson /// .field("dx", &r, &b, VectorOpt::Active)? 85008778c6fSJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &b, VectorOpt::None)? 851356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)?; 85208778c6fSJeremy L Thompson /// 85308778c6fSJeremy L Thompson /// let inputs = op.inputs()?; 85408778c6fSJeremy L Thompson /// 85508778c6fSJeremy L Thompson /// assert_eq!(inputs.len(), 2, "Incorrect inputs array"); 85608778c6fSJeremy L Thompson /// # Ok(()) 85708778c6fSJeremy L Thompson /// # } 85808778c6fSJeremy L Thompson /// ``` 859e03fef56SJeremy L Thompson pub fn inputs(&self) -> crate::Result<Vec<crate::OperatorField>> { 86008778c6fSJeremy L Thompson // Get array of raw C pointers for inputs 86108778c6fSJeremy L Thompson let mut num_inputs = 0; 86208778c6fSJeremy L Thompson let mut inputs_ptr = std::ptr::null_mut(); 863656ef1e5SJeremy L Thompson self.op_core.check_error(unsafe { 86408778c6fSJeremy L Thompson bind_ceed::CeedOperatorGetFields( 86508778c6fSJeremy L Thompson self.op_core.ptr, 86608778c6fSJeremy L Thompson &mut num_inputs, 86708778c6fSJeremy L Thompson &mut inputs_ptr, 86808778c6fSJeremy L Thompson std::ptr::null_mut() as *mut bind_ceed::CeedInt, 869bf55b007SJeremy L Thompson std::ptr::null_mut(), 87008778c6fSJeremy L Thompson ) 871656ef1e5SJeremy L Thompson })?; 87208778c6fSJeremy L Thompson // Convert raw C pointers to fixed length slice 87308778c6fSJeremy L Thompson let inputs_slice = unsafe { 87408778c6fSJeremy L Thompson std::slice::from_raw_parts( 875e03fef56SJeremy L Thompson inputs_ptr as *mut bind_ceed::CeedOperatorField, 87608778c6fSJeremy L Thompson num_inputs as usize, 87708778c6fSJeremy L Thompson ) 87808778c6fSJeremy L Thompson }; 879e03fef56SJeremy L Thompson // And finally build vec 880e03fef56SJeremy L Thompson let ceed = { 881656ef1e5SJeremy L Thompson let ceed_raw = self.op_core.ceed(); 882e03fef56SJeremy L Thompson let mut ptr = std::ptr::null_mut(); 883e03fef56SJeremy L Thompson unsafe { 884656ef1e5SJeremy L Thompson bind_ceed::CeedReferenceCopy(ceed_raw, &mut ptr); // refcount 885e03fef56SJeremy L Thompson } 886e03fef56SJeremy L Thompson crate::Ceed { ptr } 887e03fef56SJeremy L Thompson }; 888e03fef56SJeremy L Thompson let inputs = (0..num_inputs as usize) 8892b671a0aSJeremy L Thompson .map(|i| unsafe { crate::OperatorField::from_raw(inputs_slice[i], ceed.clone()) }) 890e03fef56SJeremy L Thompson .collect::<crate::Result<Vec<_>>>()?; 891e03fef56SJeremy L Thompson Ok(inputs) 89208778c6fSJeremy L Thompson } 89308778c6fSJeremy L Thompson 89408778c6fSJeremy L Thompson /// Get a slice of Operator outputs 89508778c6fSJeremy L Thompson /// 89608778c6fSJeremy L Thompson /// ``` 897eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, MemType, QFunctionOpt, QuadMode, VectorOpt}; 8984d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 89908778c6fSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 90008778c6fSJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 90108778c6fSJeremy L Thompson /// 90208778c6fSJeremy L Thompson /// // Operator field arguments 90308778c6fSJeremy L Thompson /// let ne = 3; 904bf55b007SJeremy L Thompson /// let q = 4_usize; 90508778c6fSJeremy L Thompson /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 90608778c6fSJeremy L Thompson /// for i in 0..ne { 90708778c6fSJeremy L Thompson /// ind[2 * i + 0] = i as i32; 90808778c6fSJeremy L Thompson /// ind[2 * i + 1] = (i + 1) as i32; 90908778c6fSJeremy L Thompson /// } 91008778c6fSJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 91108778c6fSJeremy L Thompson /// let strides: [i32; 3] = [1, q as i32, q as i32]; 912d9267b76SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 91308778c6fSJeremy L Thompson /// 91408778c6fSJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 91508778c6fSJeremy L Thompson /// 91608778c6fSJeremy L Thompson /// // Operator fields 91708778c6fSJeremy L Thompson /// let op = ceed 91808778c6fSJeremy L Thompson /// .operator(&qf, QFunctionOpt::None, QFunctionOpt::None)? 91908778c6fSJeremy L Thompson /// .field("dx", &r, &b, VectorOpt::Active)? 92008778c6fSJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &b, VectorOpt::None)? 921356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)?; 92208778c6fSJeremy L Thompson /// 92308778c6fSJeremy L Thompson /// let outputs = op.outputs()?; 92408778c6fSJeremy L Thompson /// 92508778c6fSJeremy L Thompson /// assert_eq!(outputs.len(), 1, "Incorrect outputs array"); 92608778c6fSJeremy L Thompson /// # Ok(()) 92708778c6fSJeremy L Thompson /// # } 92808778c6fSJeremy L Thompson /// ``` 929e03fef56SJeremy L Thompson pub fn outputs(&self) -> crate::Result<Vec<crate::OperatorField>> { 93008778c6fSJeremy L Thompson // Get array of raw C pointers for outputs 93108778c6fSJeremy L Thompson let mut num_outputs = 0; 93208778c6fSJeremy L Thompson let mut outputs_ptr = std::ptr::null_mut(); 933656ef1e5SJeremy L Thompson self.op_core.check_error(unsafe { 93408778c6fSJeremy L Thompson bind_ceed::CeedOperatorGetFields( 93508778c6fSJeremy L Thompson self.op_core.ptr, 93608778c6fSJeremy L Thompson std::ptr::null_mut() as *mut bind_ceed::CeedInt, 937bf55b007SJeremy L Thompson std::ptr::null_mut(), 93808778c6fSJeremy L Thompson &mut num_outputs, 93908778c6fSJeremy L Thompson &mut outputs_ptr, 94008778c6fSJeremy L Thompson ) 941656ef1e5SJeremy L Thompson })?; 94208778c6fSJeremy L Thompson // Convert raw C pointers to fixed length slice 94308778c6fSJeremy L Thompson let outputs_slice = unsafe { 94408778c6fSJeremy L Thompson std::slice::from_raw_parts( 945e03fef56SJeremy L Thompson outputs_ptr as *mut bind_ceed::CeedOperatorField, 94608778c6fSJeremy L Thompson num_outputs as usize, 94708778c6fSJeremy L Thompson ) 94808778c6fSJeremy L Thompson }; 949e03fef56SJeremy L Thompson // And finally build vec 950e03fef56SJeremy L Thompson let ceed = { 951656ef1e5SJeremy L Thompson let ceed_raw = self.op_core.ceed(); 952e03fef56SJeremy L Thompson let mut ptr = std::ptr::null_mut(); 953e03fef56SJeremy L Thompson unsafe { 954656ef1e5SJeremy L Thompson bind_ceed::CeedReferenceCopy(ceed_raw, &mut ptr); // refcount 955e03fef56SJeremy L Thompson } 956e03fef56SJeremy L Thompson crate::Ceed { ptr } 957e03fef56SJeremy L Thompson }; 958e03fef56SJeremy L Thompson let outputs = (0..num_outputs as usize) 9592b671a0aSJeremy L Thompson .map(|i| unsafe { crate::OperatorField::from_raw(outputs_slice[i], ceed.clone()) }) 960e03fef56SJeremy L Thompson .collect::<crate::Result<Vec<_>>>()?; 961e03fef56SJeremy L Thompson Ok(outputs) 96208778c6fSJeremy L Thompson } 96308778c6fSJeremy L Thompson 9646f97ff0aSJeremy L Thompson /// Check if Operator is setup correctly 9656f97ff0aSJeremy L Thompson /// 9666f97ff0aSJeremy L Thompson /// ``` 967eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, MemType, QFunctionOpt, QuadMode, VectorOpt}; 9686f97ff0aSJeremy L Thompson /// # fn main() -> libceed::Result<()> { 9696f97ff0aSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 9706f97ff0aSJeremy L Thompson /// let ne = 4; 9716f97ff0aSJeremy L Thompson /// let p = 3; 9726f97ff0aSJeremy L Thompson /// let q = 4; 9736f97ff0aSJeremy L Thompson /// let ndofs = p * ne - ne + 1; 9746f97ff0aSJeremy L Thompson /// 9756f97ff0aSJeremy L Thompson /// // Restrictions 9766f97ff0aSJeremy L Thompson /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 9776f97ff0aSJeremy L Thompson /// for i in 0..ne { 9786f97ff0aSJeremy L Thompson /// indx[2 * i + 0] = i as i32; 9796f97ff0aSJeremy L Thompson /// indx[2 * i + 1] = (i + 1) as i32; 9806f97ff0aSJeremy L Thompson /// } 9816f97ff0aSJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 9826f97ff0aSJeremy L Thompson /// let strides: [i32; 3] = [1, q as i32, q as i32]; 9836f97ff0aSJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 9846f97ff0aSJeremy L Thompson /// 9856f97ff0aSJeremy L Thompson /// // Bases 9866f97ff0aSJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 9876f97ff0aSJeremy L Thompson /// 9886f97ff0aSJeremy L Thompson /// // Build quadrature data 9896f97ff0aSJeremy L Thompson /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 9906f97ff0aSJeremy L Thompson /// let op_build = ceed 9916f97ff0aSJeremy L Thompson /// .operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 9926f97ff0aSJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 9936f97ff0aSJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 994356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)?; 9956f97ff0aSJeremy L Thompson /// 9966f97ff0aSJeremy L Thompson /// // Check 9976f97ff0aSJeremy L Thompson /// assert!(op_build.check().is_ok(), "Operator setup incorrectly"); 9986f97ff0aSJeremy L Thompson /// # Ok(()) 9996f97ff0aSJeremy L Thompson /// # } 10006f97ff0aSJeremy L Thompson /// ``` 10016f97ff0aSJeremy L Thompson pub fn check(self) -> crate::Result<Self> { 10026f97ff0aSJeremy L Thompson self.op_core.check()?; 10036f97ff0aSJeremy L Thompson Ok(self) 10046f97ff0aSJeremy L Thompson } 10056f97ff0aSJeremy L Thompson 10063f2759cfSJeremy L Thompson /// Get the number of elements associated with an Operator 10073f2759cfSJeremy L Thompson /// 10083f2759cfSJeremy L Thompson /// 10093f2759cfSJeremy L Thompson /// ``` 1010eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, MemType, QFunctionOpt, QuadMode, VectorOpt}; 10114d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 10123f2759cfSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 10133f2759cfSJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 10143f2759cfSJeremy L Thompson /// let mut op = ceed.operator(&qf, QFunctionOpt::None, QFunctionOpt::None)?; 10153f2759cfSJeremy L Thompson /// 10163f2759cfSJeremy L Thompson /// // Operator field arguments 10173f2759cfSJeremy L Thompson /// let ne = 3; 10183f2759cfSJeremy L Thompson /// let q = 4; 10193f2759cfSJeremy L Thompson /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 10203f2759cfSJeremy L Thompson /// for i in 0..ne { 10213f2759cfSJeremy L Thompson /// ind[2 * i + 0] = i as i32; 10223f2759cfSJeremy L Thompson /// ind[2 * i + 1] = (i + 1) as i32; 10233f2759cfSJeremy L Thompson /// } 10243f2759cfSJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 10253f2759cfSJeremy L Thompson /// 10263f2759cfSJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 10273f2759cfSJeremy L Thompson /// 10283f2759cfSJeremy L Thompson /// // Operator field 10293f2759cfSJeremy L Thompson /// op = op.field("dx", &r, &b, VectorOpt::Active)?; 10303f2759cfSJeremy L Thompson /// 10313f2759cfSJeremy L Thompson /// // Check number of elements 10323f2759cfSJeremy L Thompson /// assert_eq!(op.num_elements(), ne, "Incorrect number of elements"); 10333f2759cfSJeremy L Thompson /// # Ok(()) 10343f2759cfSJeremy L Thompson /// # } 10353f2759cfSJeremy L Thompson /// ``` 10363f2759cfSJeremy L Thompson pub fn num_elements(&self) -> usize { 10373f2759cfSJeremy L Thompson let mut nelem = 0; 10383f2759cfSJeremy L Thompson unsafe { bind_ceed::CeedOperatorGetNumElements(self.op_core.ptr, &mut nelem) }; 10393f2759cfSJeremy L Thompson usize::try_from(nelem).unwrap() 10403f2759cfSJeremy L Thompson } 10413f2759cfSJeremy L Thompson 10423f2759cfSJeremy L Thompson /// Get the number of quadrature points associated with each element of 10433f2759cfSJeremy L Thompson /// an Operator 10443f2759cfSJeremy L Thompson /// 10453f2759cfSJeremy L Thompson /// 10463f2759cfSJeremy L Thompson /// ``` 1047eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, MemType, QFunctionOpt, QuadMode, VectorOpt}; 10484d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 10493f2759cfSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 10503f2759cfSJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 10513f2759cfSJeremy L Thompson /// let mut op = ceed.operator(&qf, QFunctionOpt::None, QFunctionOpt::None)?; 10523f2759cfSJeremy L Thompson /// 10533f2759cfSJeremy L Thompson /// // Operator field arguments 10543f2759cfSJeremy L Thompson /// let ne = 3; 10553f2759cfSJeremy L Thompson /// let q = 4; 10563f2759cfSJeremy L Thompson /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 10573f2759cfSJeremy L Thompson /// for i in 0..ne { 10583f2759cfSJeremy L Thompson /// ind[2 * i + 0] = i as i32; 10593f2759cfSJeremy L Thompson /// ind[2 * i + 1] = (i + 1) as i32; 10603f2759cfSJeremy L Thompson /// } 10613f2759cfSJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 10623f2759cfSJeremy L Thompson /// 10633f2759cfSJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 10643f2759cfSJeremy L Thompson /// 10653f2759cfSJeremy L Thompson /// // Operator field 10663f2759cfSJeremy L Thompson /// op = op.field("dx", &r, &b, VectorOpt::Active)?; 10673f2759cfSJeremy L Thompson /// 10683f2759cfSJeremy L Thompson /// // Check number of quadrature points 10693f2759cfSJeremy L Thompson /// assert_eq!( 10703f2759cfSJeremy L Thompson /// op.num_quadrature_points(), 10713f2759cfSJeremy L Thompson /// q, 10723f2759cfSJeremy L Thompson /// "Incorrect number of quadrature points" 10733f2759cfSJeremy L Thompson /// ); 10743f2759cfSJeremy L Thompson /// # Ok(()) 10753f2759cfSJeremy L Thompson /// # } 10763f2759cfSJeremy L Thompson /// ``` 10773f2759cfSJeremy L Thompson pub fn num_quadrature_points(&self) -> usize { 10783f2759cfSJeremy L Thompson let mut Q = 0; 10793f2759cfSJeremy L Thompson unsafe { bind_ceed::CeedOperatorGetNumQuadraturePoints(self.op_core.ptr, &mut Q) }; 10803f2759cfSJeremy L Thompson usize::try_from(Q).unwrap() 10813f2759cfSJeremy L Thompson } 10823f2759cfSJeremy L Thompson 10839df49d7eSJed Brown /// Assemble the diagonal of a square linear Operator 10849df49d7eSJed Brown /// 10859df49d7eSJed Brown /// This overwrites a Vector with the diagonal of a linear Operator. 10869df49d7eSJed Brown /// 10879df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 10889df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 10899df49d7eSJed Brown /// 10909df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 10919df49d7eSJed Brown /// * `assembled` - Vector to store assembled Operator diagonal 10929df49d7eSJed Brown /// 10939df49d7eSJed Brown /// ``` 1094eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, MemType, QFunctionOpt, QuadMode, VectorOpt}; 10954d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 10969df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 10979df49d7eSJed Brown /// let ne = 4; 10989df49d7eSJed Brown /// let p = 3; 10999df49d7eSJed Brown /// let q = 4; 11009df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 11019df49d7eSJed Brown /// 11029df49d7eSJed Brown /// // Vectors 1103c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0])?; 1104c68be7a2SJeremy L Thompson /// let mut qdata = ceed.vector(ne * q)?; 11059df49d7eSJed Brown /// qdata.set_value(0.0); 1106c68be7a2SJeremy L Thompson /// let mut u = ceed.vector(ndofs)?; 11079df49d7eSJed Brown /// u.set_value(1.0); 1108c68be7a2SJeremy L Thompson /// let mut v = ceed.vector(ndofs)?; 11099df49d7eSJed Brown /// v.set_value(0.0); 11109df49d7eSJed Brown /// 11119df49d7eSJed Brown /// // Restrictions 11129df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 11139df49d7eSJed Brown /// for i in 0..ne { 11149df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 11159df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 11169df49d7eSJed Brown /// } 1117c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 11189df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 11199df49d7eSJed Brown /// for i in 0..ne { 11209df49d7eSJed Brown /// indu[p * i + 0] = (2 * i) as i32; 11219df49d7eSJed Brown /// indu[p * i + 1] = (2 * i + 1) as i32; 11229df49d7eSJed Brown /// indu[p * i + 2] = (2 * i + 2) as i32; 11239df49d7eSJed Brown /// } 1124c68be7a2SJeremy L Thompson /// let ru = ceed.elem_restriction(ne, p, 1, 1, ndofs, MemType::Host, &indu)?; 11259df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 1126c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 11279df49d7eSJed Brown /// 11289df49d7eSJed Brown /// // Bases 1129c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 1130c68be7a2SJeremy L Thompson /// let bu = ceed.basis_tensor_H1_Lagrange(1, 1, p, q, QuadMode::Gauss)?; 11319df49d7eSJed Brown /// 11329df49d7eSJed Brown /// // Build quadrature data 1133c68be7a2SJeremy L Thompson /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 1134c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 1135c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 1136c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 1137356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)? 1138c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata)?; 11399df49d7eSJed Brown /// 11409df49d7eSJed Brown /// // Mass operator 1141c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 11429df49d7eSJed Brown /// let op_mass = ceed 1143c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 1144c68be7a2SJeremy L Thompson /// .field("u", &ru, &bu, VectorOpt::Active)? 1145356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, &qdata)? 1146c68be7a2SJeremy L Thompson /// .field("v", &ru, &bu, VectorOpt::Active)?; 11479df49d7eSJed Brown /// 11489df49d7eSJed Brown /// // Diagonal 1149c68be7a2SJeremy L Thompson /// let mut diag = ceed.vector(ndofs)?; 11509df49d7eSJed Brown /// diag.set_value(0.0); 1151c68be7a2SJeremy L Thompson /// op_mass.linear_assemble_diagonal(&mut diag)?; 11529df49d7eSJed Brown /// 11539df49d7eSJed Brown /// // Manual diagonal computation 1154c68be7a2SJeremy L Thompson /// let mut true_diag = ceed.vector(ndofs)?; 11559c774eddSJeremy L Thompson /// true_diag.set_value(0.0)?; 11569df49d7eSJed Brown /// for i in 0..ndofs { 11579df49d7eSJed Brown /// u.set_value(0.0); 11589df49d7eSJed Brown /// { 1159e78171edSJeremy L Thompson /// let mut u_array = u.view_mut()?; 11609df49d7eSJed Brown /// u_array[i] = 1.; 11619df49d7eSJed Brown /// } 11629df49d7eSJed Brown /// 1163c68be7a2SJeremy L Thompson /// op_mass.apply(&u, &mut v)?; 11649df49d7eSJed Brown /// 11659df49d7eSJed Brown /// { 11669c774eddSJeremy L Thompson /// let v_array = v.view()?; 1167e78171edSJeremy L Thompson /// let mut true_array = true_diag.view_mut()?; 11689df49d7eSJed Brown /// true_array[i] = v_array[i]; 11699df49d7eSJed Brown /// } 11709df49d7eSJed Brown /// } 11719df49d7eSJed Brown /// 11729df49d7eSJed Brown /// // Check 1173e78171edSJeremy L Thompson /// diag.view()? 11749df49d7eSJed Brown /// .iter() 1175e78171edSJeremy L Thompson /// .zip(true_diag.view()?.iter()) 11769df49d7eSJed Brown /// .for_each(|(computed, actual)| { 11779df49d7eSJed Brown /// assert!( 117880a9ef05SNatalie Beams /// (*computed - *actual).abs() < 10.0 * libceed::EPSILON, 11799df49d7eSJed Brown /// "Diagonal entry incorrect" 11809df49d7eSJed Brown /// ); 11819df49d7eSJed Brown /// }); 1182c68be7a2SJeremy L Thompson /// # Ok(()) 1183c68be7a2SJeremy L Thompson /// # } 11849df49d7eSJed Brown /// ``` 11859df49d7eSJed Brown pub fn linear_assemble_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> { 11869df49d7eSJed Brown self.op_core.linear_assemble_diagonal(assembled) 11879df49d7eSJed Brown } 11889df49d7eSJed Brown 11899df49d7eSJed Brown /// Assemble the diagonal of a square linear Operator 11909df49d7eSJed Brown /// 11919df49d7eSJed Brown /// This sums into a Vector with the diagonal of a linear Operator. 11929df49d7eSJed Brown /// 11939df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 11949df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 11959df49d7eSJed Brown /// 11969df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 11979df49d7eSJed Brown /// * `assembled` - Vector to store assembled Operator diagonal 11989df49d7eSJed Brown /// 11999df49d7eSJed Brown /// 12009df49d7eSJed Brown /// ``` 1201eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, MemType, QFunctionOpt, QuadMode, Scalar, VectorOpt}; 12024d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 12039df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 12049df49d7eSJed Brown /// let ne = 4; 12059df49d7eSJed Brown /// let p = 3; 12069df49d7eSJed Brown /// let q = 4; 12079df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 12089df49d7eSJed Brown /// 12099df49d7eSJed Brown /// // Vectors 1210c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0])?; 1211c68be7a2SJeremy L Thompson /// let mut qdata = ceed.vector(ne * q)?; 12129df49d7eSJed Brown /// qdata.set_value(0.0); 1213c68be7a2SJeremy L Thompson /// let mut u = ceed.vector(ndofs)?; 12149df49d7eSJed Brown /// u.set_value(1.0); 1215c68be7a2SJeremy L Thompson /// let mut v = ceed.vector(ndofs)?; 12169df49d7eSJed Brown /// v.set_value(0.0); 12179df49d7eSJed Brown /// 12189df49d7eSJed Brown /// // Restrictions 12199df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 12209df49d7eSJed Brown /// for i in 0..ne { 12219df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 12229df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 12239df49d7eSJed Brown /// } 1224c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 12259df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 12269df49d7eSJed Brown /// for i in 0..ne { 12279df49d7eSJed Brown /// indu[p * i + 0] = (2 * i) as i32; 12289df49d7eSJed Brown /// indu[p * i + 1] = (2 * i + 1) as i32; 12299df49d7eSJed Brown /// indu[p * i + 2] = (2 * i + 2) as i32; 12309df49d7eSJed Brown /// } 1231c68be7a2SJeremy L Thompson /// let ru = ceed.elem_restriction(ne, p, 1, 1, ndofs, MemType::Host, &indu)?; 12329df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 1233c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 12349df49d7eSJed Brown /// 12359df49d7eSJed Brown /// // Bases 1236c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 1237c68be7a2SJeremy L Thompson /// let bu = ceed.basis_tensor_H1_Lagrange(1, 1, p, q, QuadMode::Gauss)?; 12389df49d7eSJed Brown /// 12399df49d7eSJed Brown /// // Build quadrature data 1240c68be7a2SJeremy L Thompson /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 1241c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 1242c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 1243c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 1244356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)? 1245c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata)?; 12469df49d7eSJed Brown /// 12479df49d7eSJed Brown /// // Mass operator 1248c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 12499df49d7eSJed Brown /// let op_mass = ceed 1250c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 1251c68be7a2SJeremy L Thompson /// .field("u", &ru, &bu, VectorOpt::Active)? 1252356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, &qdata)? 1253c68be7a2SJeremy L Thompson /// .field("v", &ru, &bu, VectorOpt::Active)?; 12549df49d7eSJed Brown /// 12559df49d7eSJed Brown /// // Diagonal 1256c68be7a2SJeremy L Thompson /// let mut diag = ceed.vector(ndofs)?; 12579df49d7eSJed Brown /// diag.set_value(1.0); 1258c68be7a2SJeremy L Thompson /// op_mass.linear_assemble_add_diagonal(&mut diag)?; 12599df49d7eSJed Brown /// 12609df49d7eSJed Brown /// // Manual diagonal computation 1261c68be7a2SJeremy L Thompson /// let mut true_diag = ceed.vector(ndofs)?; 12629c774eddSJeremy L Thompson /// true_diag.set_value(0.0)?; 12639df49d7eSJed Brown /// for i in 0..ndofs { 12649df49d7eSJed Brown /// u.set_value(0.0); 12659df49d7eSJed Brown /// { 1266e78171edSJeremy L Thompson /// let mut u_array = u.view_mut()?; 12679df49d7eSJed Brown /// u_array[i] = 1.; 12689df49d7eSJed Brown /// } 12699df49d7eSJed Brown /// 1270c68be7a2SJeremy L Thompson /// op_mass.apply(&u, &mut v)?; 12719df49d7eSJed Brown /// 12729df49d7eSJed Brown /// { 12739c774eddSJeremy L Thompson /// let v_array = v.view()?; 1274e78171edSJeremy L Thompson /// let mut true_array = true_diag.view_mut()?; 12759df49d7eSJed Brown /// true_array[i] = v_array[i] + 1.0; 12769df49d7eSJed Brown /// } 12779df49d7eSJed Brown /// } 12789df49d7eSJed Brown /// 12799df49d7eSJed Brown /// // Check 1280e78171edSJeremy L Thompson /// diag.view()? 12819df49d7eSJed Brown /// .iter() 1282e78171edSJeremy L Thompson /// .zip(true_diag.view()?.iter()) 12839df49d7eSJed Brown /// .for_each(|(computed, actual)| { 12849df49d7eSJed Brown /// assert!( 128580a9ef05SNatalie Beams /// (*computed - *actual).abs() < 10.0 * libceed::EPSILON, 12869df49d7eSJed Brown /// "Diagonal entry incorrect" 12879df49d7eSJed Brown /// ); 12889df49d7eSJed Brown /// }); 1289c68be7a2SJeremy L Thompson /// # Ok(()) 1290c68be7a2SJeremy L Thompson /// # } 12919df49d7eSJed Brown /// ``` 12929df49d7eSJed Brown pub fn linear_assemble_add_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> { 12939df49d7eSJed Brown self.op_core.linear_assemble_add_diagonal(assembled) 12949df49d7eSJed Brown } 12959df49d7eSJed Brown 12969df49d7eSJed Brown /// Assemble the point block diagonal of a square linear Operator 12979df49d7eSJed Brown /// 12989df49d7eSJed Brown /// This overwrites a Vector with the point block diagonal of a linear 12999df49d7eSJed Brown /// Operator. 13009df49d7eSJed Brown /// 13019df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 13029df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 13039df49d7eSJed Brown /// 13049df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 13059df49d7eSJed Brown /// * `assembled` - Vector to store assembled CeedOperator point block 13069df49d7eSJed Brown /// diagonal, provided in row-major form with an 13079df49d7eSJed Brown /// `ncomp * ncomp` block at each node. The dimensions of 13089df49d7eSJed Brown /// this vector are derived from the active vector for 13099df49d7eSJed Brown /// the CeedOperator. The array has shape 13109df49d7eSJed Brown /// `[nodes, component out, component in]`. 13119df49d7eSJed Brown /// 13129df49d7eSJed Brown /// ``` 1313eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, EvalMode, MemType, QFunctionInputs, QFunctionOpt, QFunctionOutputs, QuadMode, VectorOpt}; 13144d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 13159df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 13169df49d7eSJed Brown /// let ne = 4; 13179df49d7eSJed Brown /// let p = 3; 13189df49d7eSJed Brown /// let q = 4; 13199df49d7eSJed Brown /// let ncomp = 2; 13209df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 13219df49d7eSJed Brown /// 13229df49d7eSJed Brown /// // Vectors 1323c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0])?; 1324c68be7a2SJeremy L Thompson /// let mut qdata = ceed.vector(ne * q)?; 13259df49d7eSJed Brown /// qdata.set_value(0.0); 1326c68be7a2SJeremy L Thompson /// let mut u = ceed.vector(ncomp * ndofs)?; 13279df49d7eSJed Brown /// u.set_value(1.0); 1328c68be7a2SJeremy L Thompson /// let mut v = ceed.vector(ncomp * ndofs)?; 13299df49d7eSJed Brown /// v.set_value(0.0); 13309df49d7eSJed Brown /// 13319df49d7eSJed Brown /// // Restrictions 13329df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 13339df49d7eSJed Brown /// for i in 0..ne { 13349df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 13359df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 13369df49d7eSJed Brown /// } 1337c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 13389df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 13399df49d7eSJed Brown /// for i in 0..ne { 13409df49d7eSJed Brown /// indu[p * i + 0] = (2 * i) as i32; 13419df49d7eSJed Brown /// indu[p * i + 1] = (2 * i + 1) as i32; 13429df49d7eSJed Brown /// indu[p * i + 2] = (2 * i + 2) as i32; 13439df49d7eSJed Brown /// } 1344c68be7a2SJeremy L Thompson /// let ru = ceed.elem_restriction(ne, p, ncomp, ndofs, ncomp * ndofs, MemType::Host, &indu)?; 13459df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 1346c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 13479df49d7eSJed Brown /// 13489df49d7eSJed Brown /// // Bases 1349c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 1350c68be7a2SJeremy L Thompson /// let bu = ceed.basis_tensor_H1_Lagrange(1, ncomp, p, q, QuadMode::Gauss)?; 13519df49d7eSJed Brown /// 13529df49d7eSJed Brown /// // Build quadrature data 1353c68be7a2SJeremy L Thompson /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 1354c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 1355c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 1356c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 1357356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)? 1358c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata)?; 13599df49d7eSJed Brown /// 13609df49d7eSJed Brown /// // Mass operator 13619df49d7eSJed Brown /// let mut mass_2_comp = |[u, qdata, ..]: QFunctionInputs, [v, ..]: QFunctionOutputs| { 13629df49d7eSJed Brown /// // Number of quadrature points 13639df49d7eSJed Brown /// let q = qdata.len(); 13649df49d7eSJed Brown /// 13659df49d7eSJed Brown /// // Iterate over quadrature points 13669df49d7eSJed Brown /// for i in 0..q { 13679df49d7eSJed Brown /// v[i + 0 * q] = u[i + 1 * q] * qdata[i]; 13689df49d7eSJed Brown /// v[i + 1 * q] = u[i + 0 * q] * qdata[i]; 13699df49d7eSJed Brown /// } 13709df49d7eSJed Brown /// 13719df49d7eSJed Brown /// // Return clean error code 13729df49d7eSJed Brown /// 0 13739df49d7eSJed Brown /// }; 13749df49d7eSJed Brown /// 13759df49d7eSJed Brown /// let qf_mass = ceed 1376c68be7a2SJeremy L Thompson /// .q_function_interior(1, Box::new(mass_2_comp))? 1377c68be7a2SJeremy L Thompson /// .input("u", 2, EvalMode::Interp)? 1378c68be7a2SJeremy L Thompson /// .input("qdata", 1, EvalMode::None)? 1379c68be7a2SJeremy L Thompson /// .output("v", 2, EvalMode::Interp)?; 13809df49d7eSJed Brown /// 13819df49d7eSJed Brown /// let op_mass = ceed 1382c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 1383c68be7a2SJeremy L Thompson /// .field("u", &ru, &bu, VectorOpt::Active)? 1384356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, &qdata)? 1385c68be7a2SJeremy L Thompson /// .field("v", &ru, &bu, VectorOpt::Active)?; 13869df49d7eSJed Brown /// 13879df49d7eSJed Brown /// // Diagonal 1388c68be7a2SJeremy L Thompson /// let mut diag = ceed.vector(ncomp * ncomp * ndofs)?; 13899df49d7eSJed Brown /// diag.set_value(0.0); 1390c68be7a2SJeremy L Thompson /// op_mass.linear_assemble_point_block_diagonal(&mut diag)?; 13919df49d7eSJed Brown /// 13929df49d7eSJed Brown /// // Manual diagonal computation 1393c68be7a2SJeremy L Thompson /// let mut true_diag = ceed.vector(ncomp * ncomp * ndofs)?; 13949c774eddSJeremy L Thompson /// true_diag.set_value(0.0)?; 13959df49d7eSJed Brown /// for i in 0..ndofs { 13969df49d7eSJed Brown /// for j in 0..ncomp { 13979df49d7eSJed Brown /// u.set_value(0.0); 13989df49d7eSJed Brown /// { 1399e78171edSJeremy L Thompson /// let mut u_array = u.view_mut()?; 14009df49d7eSJed Brown /// u_array[i + j * ndofs] = 1.; 14019df49d7eSJed Brown /// } 14029df49d7eSJed Brown /// 1403c68be7a2SJeremy L Thompson /// op_mass.apply(&u, &mut v)?; 14049df49d7eSJed Brown /// 14059df49d7eSJed Brown /// { 14069c774eddSJeremy L Thompson /// let v_array = v.view()?; 1407e78171edSJeremy L Thompson /// let mut true_array = true_diag.view_mut()?; 14089df49d7eSJed Brown /// for k in 0..ncomp { 14099df49d7eSJed Brown /// true_array[i * ncomp * ncomp + k * ncomp + j] = v_array[i + k * ndofs]; 14109df49d7eSJed Brown /// } 14119df49d7eSJed Brown /// } 14129df49d7eSJed Brown /// } 14139df49d7eSJed Brown /// } 14149df49d7eSJed Brown /// 14159df49d7eSJed Brown /// // Check 1416e78171edSJeremy L Thompson /// diag.view()? 14179df49d7eSJed Brown /// .iter() 1418e78171edSJeremy L Thompson /// .zip(true_diag.view()?.iter()) 14199df49d7eSJed Brown /// .for_each(|(computed, actual)| { 14209df49d7eSJed Brown /// assert!( 142180a9ef05SNatalie Beams /// (*computed - *actual).abs() < 10.0 * libceed::EPSILON, 14229df49d7eSJed Brown /// "Diagonal entry incorrect" 14239df49d7eSJed Brown /// ); 14249df49d7eSJed Brown /// }); 1425c68be7a2SJeremy L Thompson /// # Ok(()) 1426c68be7a2SJeremy L Thompson /// # } 14279df49d7eSJed Brown /// ``` 14289df49d7eSJed Brown pub fn linear_assemble_point_block_diagonal( 14299df49d7eSJed Brown &self, 14309df49d7eSJed Brown assembled: &mut Vector, 14319df49d7eSJed Brown ) -> crate::Result<i32> { 14329df49d7eSJed Brown self.op_core.linear_assemble_point_block_diagonal(assembled) 14339df49d7eSJed Brown } 14349df49d7eSJed Brown 14359df49d7eSJed Brown /// Assemble the point block diagonal of a square linear Operator 14369df49d7eSJed Brown /// 14379df49d7eSJed Brown /// This sums into a Vector with the point block diagonal of a linear 14389df49d7eSJed Brown /// Operator. 14399df49d7eSJed Brown /// 14409df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 14419df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 14429df49d7eSJed Brown /// 14439df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 14449df49d7eSJed Brown /// * `assembled` - Vector to store assembled CeedOperator point block 14459df49d7eSJed Brown /// diagonal, provided in row-major form with an 14469df49d7eSJed Brown /// `ncomp * ncomp` block at each node. The dimensions of 14479df49d7eSJed Brown /// this vector are derived from the active vector for 14489df49d7eSJed Brown /// the CeedOperator. The array has shape 14499df49d7eSJed Brown /// `[nodes, component out, component in]`. 14509df49d7eSJed Brown /// 14519df49d7eSJed Brown /// ``` 1452eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, EvalMode, MemType, QFunctionInputs, QFunctionOpt, QFunctionOutputs, QuadMode, Scalar, VectorOpt}; 14534d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 14549df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 14559df49d7eSJed Brown /// let ne = 4; 14569df49d7eSJed Brown /// let p = 3; 14579df49d7eSJed Brown /// let q = 4; 14589df49d7eSJed Brown /// let ncomp = 2; 14599df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 14609df49d7eSJed Brown /// 14619df49d7eSJed Brown /// // Vectors 1462c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0])?; 1463c68be7a2SJeremy L Thompson /// let mut qdata = ceed.vector(ne * q)?; 14649df49d7eSJed Brown /// qdata.set_value(0.0); 1465c68be7a2SJeremy L Thompson /// let mut u = ceed.vector(ncomp * ndofs)?; 14669df49d7eSJed Brown /// u.set_value(1.0); 1467c68be7a2SJeremy L Thompson /// let mut v = ceed.vector(ncomp * ndofs)?; 14689df49d7eSJed Brown /// v.set_value(0.0); 14699df49d7eSJed Brown /// 14709df49d7eSJed Brown /// // Restrictions 14719df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 14729df49d7eSJed Brown /// for i in 0..ne { 14739df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 14749df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 14759df49d7eSJed Brown /// } 1476c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 14779df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 14789df49d7eSJed Brown /// for i in 0..ne { 14799df49d7eSJed Brown /// indu[p * i + 0] = (2 * i) as i32; 14809df49d7eSJed Brown /// indu[p * i + 1] = (2 * i + 1) as i32; 14819df49d7eSJed Brown /// indu[p * i + 2] = (2 * i + 2) as i32; 14829df49d7eSJed Brown /// } 1483c68be7a2SJeremy L Thompson /// let ru = ceed.elem_restriction(ne, p, ncomp, ndofs, ncomp * ndofs, MemType::Host, &indu)?; 14849df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 1485c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 14869df49d7eSJed Brown /// 14879df49d7eSJed Brown /// // Bases 1488c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 1489c68be7a2SJeremy L Thompson /// let bu = ceed.basis_tensor_H1_Lagrange(1, ncomp, p, q, QuadMode::Gauss)?; 14909df49d7eSJed Brown /// 14919df49d7eSJed Brown /// // Build quadrature data 1492c68be7a2SJeremy L Thompson /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 1493c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 1494c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 1495c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 1496356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)? 1497c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata)?; 14989df49d7eSJed Brown /// 14999df49d7eSJed Brown /// // Mass operator 15009df49d7eSJed Brown /// let mut mass_2_comp = |[u, qdata, ..]: QFunctionInputs, [v, ..]: QFunctionOutputs| { 15019df49d7eSJed Brown /// // Number of quadrature points 15029df49d7eSJed Brown /// let q = qdata.len(); 15039df49d7eSJed Brown /// 15049df49d7eSJed Brown /// // Iterate over quadrature points 15059df49d7eSJed Brown /// for i in 0..q { 15069df49d7eSJed Brown /// v[i + 0 * q] = u[i + 1 * q] * qdata[i]; 15079df49d7eSJed Brown /// v[i + 1 * q] = u[i + 0 * q] * qdata[i]; 15089df49d7eSJed Brown /// } 15099df49d7eSJed Brown /// 15109df49d7eSJed Brown /// // Return clean error code 15119df49d7eSJed Brown /// 0 15129df49d7eSJed Brown /// }; 15139df49d7eSJed Brown /// 15149df49d7eSJed Brown /// let qf_mass = ceed 1515c68be7a2SJeremy L Thompson /// .q_function_interior(1, Box::new(mass_2_comp))? 1516c68be7a2SJeremy L Thompson /// .input("u", 2, EvalMode::Interp)? 1517c68be7a2SJeremy L Thompson /// .input("qdata", 1, EvalMode::None)? 1518c68be7a2SJeremy L Thompson /// .output("v", 2, EvalMode::Interp)?; 15199df49d7eSJed Brown /// 15209df49d7eSJed Brown /// let op_mass = ceed 1521c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 1522c68be7a2SJeremy L Thompson /// .field("u", &ru, &bu, VectorOpt::Active)? 1523356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, &qdata)? 1524c68be7a2SJeremy L Thompson /// .field("v", &ru, &bu, VectorOpt::Active)?; 15259df49d7eSJed Brown /// 15269df49d7eSJed Brown /// // Diagonal 1527c68be7a2SJeremy L Thompson /// let mut diag = ceed.vector(ncomp * ncomp * ndofs)?; 15289df49d7eSJed Brown /// diag.set_value(1.0); 1529c68be7a2SJeremy L Thompson /// op_mass.linear_assemble_add_point_block_diagonal(&mut diag)?; 15309df49d7eSJed Brown /// 15319df49d7eSJed Brown /// // Manual diagonal computation 1532c68be7a2SJeremy L Thompson /// let mut true_diag = ceed.vector(ncomp * ncomp * ndofs)?; 15339c774eddSJeremy L Thompson /// true_diag.set_value(0.0)?; 15349df49d7eSJed Brown /// for i in 0..ndofs { 15359df49d7eSJed Brown /// for j in 0..ncomp { 15369df49d7eSJed Brown /// u.set_value(0.0); 15379df49d7eSJed Brown /// { 1538e78171edSJeremy L Thompson /// let mut u_array = u.view_mut()?; 15399df49d7eSJed Brown /// u_array[i + j * ndofs] = 1.; 15409df49d7eSJed Brown /// } 15419df49d7eSJed Brown /// 1542c68be7a2SJeremy L Thompson /// op_mass.apply(&u, &mut v)?; 15439df49d7eSJed Brown /// 15449df49d7eSJed Brown /// { 15459c774eddSJeremy L Thompson /// let v_array = v.view()?; 1546e78171edSJeremy L Thompson /// let mut true_array = true_diag.view_mut()?; 15479df49d7eSJed Brown /// for k in 0..ncomp { 15489df49d7eSJed Brown /// true_array[i * ncomp * ncomp + k * ncomp + j] = v_array[i + k * ndofs]; 15499df49d7eSJed Brown /// } 15509df49d7eSJed Brown /// } 15519df49d7eSJed Brown /// } 15529df49d7eSJed Brown /// } 15539df49d7eSJed Brown /// 15549df49d7eSJed Brown /// // Check 1555e78171edSJeremy L Thompson /// diag.view()? 15569df49d7eSJed Brown /// .iter() 1557e78171edSJeremy L Thompson /// .zip(true_diag.view()?.iter()) 15589df49d7eSJed Brown /// .for_each(|(computed, actual)| { 15599df49d7eSJed Brown /// assert!( 156080a9ef05SNatalie Beams /// (*computed - 1.0 - *actual).abs() < 10.0 * libceed::EPSILON, 15619df49d7eSJed Brown /// "Diagonal entry incorrect" 15629df49d7eSJed Brown /// ); 15639df49d7eSJed Brown /// }); 1564c68be7a2SJeremy L Thompson /// # Ok(()) 1565c68be7a2SJeremy L Thompson /// # } 15669df49d7eSJed Brown /// ``` 15679df49d7eSJed Brown pub fn linear_assemble_add_point_block_diagonal( 15689df49d7eSJed Brown &self, 15699df49d7eSJed Brown assembled: &mut Vector, 15709df49d7eSJed Brown ) -> crate::Result<i32> { 15719df49d7eSJed Brown self.op_core 15729df49d7eSJed Brown .linear_assemble_add_point_block_diagonal(assembled) 15739df49d7eSJed Brown } 15749df49d7eSJed Brown 15759df49d7eSJed Brown /// Create a multigrid coarse Operator and level transfer Operators for a 15769df49d7eSJed Brown /// given Operator, creating the prolongation basis from the fine and 15779df49d7eSJed Brown /// coarse grid interpolation 15789df49d7eSJed Brown /// 15799df49d7eSJed Brown /// * `p_mult_fine` - Lvector multiplicity in parallel gather/scatter 15809df49d7eSJed Brown /// * `rstr_coarse` - Coarse grid restriction 15819df49d7eSJed Brown /// * `basis_coarse` - Coarse grid active vector basis 15829df49d7eSJed Brown /// 15839df49d7eSJed Brown /// ``` 1584eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, MemType, QFunctionOpt, QuadMode, Scalar, VectorOpt}; 15854d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 15869df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 15879df49d7eSJed Brown /// let ne = 15; 15889df49d7eSJed Brown /// let p_coarse = 3; 15899df49d7eSJed Brown /// let p_fine = 5; 15909df49d7eSJed Brown /// let q = 6; 15919df49d7eSJed Brown /// let ndofs_coarse = p_coarse * ne - ne + 1; 15929df49d7eSJed Brown /// let ndofs_fine = p_fine * ne - ne + 1; 15939df49d7eSJed Brown /// 15949df49d7eSJed Brown /// // Vectors 15959df49d7eSJed Brown /// let x_array = (0..ne + 1) 159680a9ef05SNatalie Beams /// .map(|i| 2.0 * i as Scalar / ne as Scalar - 1.0) 159780a9ef05SNatalie Beams /// .collect::<Vec<Scalar>>(); 1598c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&x_array)?; 1599c68be7a2SJeremy L Thompson /// let mut qdata = ceed.vector(ne * q)?; 16009df49d7eSJed Brown /// qdata.set_value(0.0); 1601c68be7a2SJeremy L Thompson /// let mut u_coarse = ceed.vector(ndofs_coarse)?; 16029df49d7eSJed Brown /// u_coarse.set_value(1.0); 1603c68be7a2SJeremy L Thompson /// let mut u_fine = ceed.vector(ndofs_fine)?; 16049df49d7eSJed Brown /// u_fine.set_value(1.0); 1605c68be7a2SJeremy L Thompson /// let mut v_coarse = ceed.vector(ndofs_coarse)?; 16069df49d7eSJed Brown /// v_coarse.set_value(0.0); 1607c68be7a2SJeremy L Thompson /// let mut v_fine = ceed.vector(ndofs_fine)?; 16089df49d7eSJed Brown /// v_fine.set_value(0.0); 1609c68be7a2SJeremy L Thompson /// let mut multiplicity = ceed.vector(ndofs_fine)?; 16109df49d7eSJed Brown /// multiplicity.set_value(1.0); 16119df49d7eSJed Brown /// 16129df49d7eSJed Brown /// // Restrictions 16139df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 1614c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 16159df49d7eSJed Brown /// 16169df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 16179df49d7eSJed Brown /// for i in 0..ne { 16189df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 16199df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 16209df49d7eSJed Brown /// } 1621c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 16229df49d7eSJed Brown /// 16239df49d7eSJed Brown /// let mut indu_coarse: Vec<i32> = vec![0; p_coarse * ne]; 16249df49d7eSJed Brown /// for i in 0..ne { 16259df49d7eSJed Brown /// for j in 0..p_coarse { 16269df49d7eSJed Brown /// indu_coarse[p_coarse * i + j] = (i + j) as i32; 16279df49d7eSJed Brown /// } 16289df49d7eSJed Brown /// } 1629c68be7a2SJeremy L Thompson /// let ru_coarse = ceed.elem_restriction( 16309df49d7eSJed Brown /// ne, 16319df49d7eSJed Brown /// p_coarse, 16329df49d7eSJed Brown /// 1, 16339df49d7eSJed Brown /// 1, 16349df49d7eSJed Brown /// ndofs_coarse, 16359df49d7eSJed Brown /// MemType::Host, 16369df49d7eSJed Brown /// &indu_coarse, 1637c68be7a2SJeremy L Thompson /// )?; 16389df49d7eSJed Brown /// 16399df49d7eSJed Brown /// let mut indu_fine: Vec<i32> = vec![0; p_fine * ne]; 16409df49d7eSJed Brown /// for i in 0..ne { 16419df49d7eSJed Brown /// for j in 0..p_fine { 16429df49d7eSJed Brown /// indu_fine[p_fine * i + j] = (i + j) as i32; 16439df49d7eSJed Brown /// } 16449df49d7eSJed Brown /// } 1645c68be7a2SJeremy L Thompson /// let ru_fine = ceed.elem_restriction(ne, p_fine, 1, 1, ndofs_fine, MemType::Host, &indu_fine)?; 16469df49d7eSJed Brown /// 16479df49d7eSJed Brown /// // Bases 1648c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 1649c68be7a2SJeremy L Thompson /// let bu_coarse = ceed.basis_tensor_H1_Lagrange(1, 1, p_coarse, q, QuadMode::Gauss)?; 1650c68be7a2SJeremy L Thompson /// let bu_fine = ceed.basis_tensor_H1_Lagrange(1, 1, p_fine, q, QuadMode::Gauss)?; 16519df49d7eSJed Brown /// 16529df49d7eSJed Brown /// // Build quadrature data 1653c68be7a2SJeremy L Thompson /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 1654c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 1655c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 1656c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 1657356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)? 1658c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata)?; 16599df49d7eSJed Brown /// 16609df49d7eSJed Brown /// // Mass operator 1661c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 16629df49d7eSJed Brown /// let op_mass_fine = ceed 1663c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 1664c68be7a2SJeremy L Thompson /// .field("u", &ru_fine, &bu_fine, VectorOpt::Active)? 1665356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, &qdata)? 1666c68be7a2SJeremy L Thompson /// .field("v", &ru_fine, &bu_fine, VectorOpt::Active)?; 16679df49d7eSJed Brown /// 16689df49d7eSJed Brown /// // Multigrid setup 1669c68be7a2SJeremy L Thompson /// let (op_mass_coarse, op_prolong, op_restrict) = 1670c68be7a2SJeremy L Thompson /// op_mass_fine.create_multigrid_level(&multiplicity, &ru_coarse, &bu_coarse)?; 16719df49d7eSJed Brown /// 16729df49d7eSJed Brown /// // Coarse problem 16739df49d7eSJed Brown /// u_coarse.set_value(1.0); 1674c68be7a2SJeremy L Thompson /// op_mass_coarse.apply(&u_coarse, &mut v_coarse)?; 16759df49d7eSJed Brown /// 16769df49d7eSJed Brown /// // Check 1677e78171edSJeremy L Thompson /// let sum: Scalar = v_coarse.view()?.iter().sum(); 16789df49d7eSJed Brown /// assert!( 167980a9ef05SNatalie Beams /// (sum - 2.0).abs() < 50.0 * libceed::EPSILON, 16809df49d7eSJed Brown /// "Incorrect interval length computed" 16819df49d7eSJed Brown /// ); 16829df49d7eSJed Brown /// 16839df49d7eSJed Brown /// // Prolong 1684c68be7a2SJeremy L Thompson /// op_prolong.apply(&u_coarse, &mut u_fine)?; 16859df49d7eSJed Brown /// 16869df49d7eSJed Brown /// // Fine problem 1687c68be7a2SJeremy L Thompson /// op_mass_fine.apply(&u_fine, &mut v_fine)?; 16889df49d7eSJed Brown /// 16899df49d7eSJed Brown /// // Check 1690e78171edSJeremy L Thompson /// let sum: Scalar = v_fine.view()?.iter().sum(); 16919df49d7eSJed Brown /// assert!( 1692392d940cSJeremy L Thompson /// (sum - 2.0).abs() < 200.0 * libceed::EPSILON, 16939df49d7eSJed Brown /// "Incorrect interval length computed" 16949df49d7eSJed Brown /// ); 16959df49d7eSJed Brown /// 16969df49d7eSJed Brown /// // Restrict 1697c68be7a2SJeremy L Thompson /// op_restrict.apply(&v_fine, &mut v_coarse)?; 16989df49d7eSJed Brown /// 16999df49d7eSJed Brown /// // Check 1700e78171edSJeremy L Thompson /// let sum: Scalar = v_coarse.view()?.iter().sum(); 17019df49d7eSJed Brown /// assert!( 1702392d940cSJeremy L Thompson /// (sum - 2.0).abs() < 200.0 * libceed::EPSILON, 17039df49d7eSJed Brown /// "Incorrect interval length computed" 17049df49d7eSJed Brown /// ); 1705c68be7a2SJeremy L Thompson /// # Ok(()) 1706c68be7a2SJeremy L Thompson /// # } 17079df49d7eSJed Brown /// ``` 1708594ef120SJeremy L Thompson pub fn create_multigrid_level<'b>( 17099df49d7eSJed Brown &self, 17109df49d7eSJed Brown p_mult_fine: &Vector, 17119df49d7eSJed Brown rstr_coarse: &ElemRestriction, 17129df49d7eSJed Brown basis_coarse: &Basis, 1713594ef120SJeremy L Thompson ) -> crate::Result<(Operator<'b>, Operator<'b>, Operator<'b>)> { 17149df49d7eSJed Brown let mut ptr_coarse = std::ptr::null_mut(); 17159df49d7eSJed Brown let mut ptr_prolong = std::ptr::null_mut(); 17169df49d7eSJed Brown let mut ptr_restrict = std::ptr::null_mut(); 1717656ef1e5SJeremy L Thompson self.op_core.check_error(unsafe { 17189df49d7eSJed Brown bind_ceed::CeedOperatorMultigridLevelCreate( 17199df49d7eSJed Brown self.op_core.ptr, 17209df49d7eSJed Brown p_mult_fine.ptr, 17219df49d7eSJed Brown rstr_coarse.ptr, 17229df49d7eSJed Brown basis_coarse.ptr, 17239df49d7eSJed Brown &mut ptr_coarse, 17249df49d7eSJed Brown &mut ptr_prolong, 17259df49d7eSJed Brown &mut ptr_restrict, 17269df49d7eSJed Brown ) 1727656ef1e5SJeremy L Thompson })?; 17282b671a0aSJeremy L Thompson let op_coarse = unsafe { Operator::from_raw(ptr_coarse)? }; 17292b671a0aSJeremy L Thompson let op_prolong = unsafe { Operator::from_raw(ptr_prolong)? }; 17302b671a0aSJeremy L Thompson let op_restrict = unsafe { Operator::from_raw(ptr_restrict)? }; 17319df49d7eSJed Brown Ok((op_coarse, op_prolong, op_restrict)) 17329df49d7eSJed Brown } 17339df49d7eSJed Brown 17349df49d7eSJed Brown /// Create a multigrid coarse Operator and level transfer Operators for a 17359df49d7eSJed Brown /// given Operator with a tensor basis for the active basis 17369df49d7eSJed Brown /// 17379df49d7eSJed Brown /// * `p_mult_fine` - Lvector multiplicity in parallel gather/scatter 17389df49d7eSJed Brown /// * `rstr_coarse` - Coarse grid restriction 17399df49d7eSJed Brown /// * `basis_coarse` - Coarse grid active vector basis 17409df49d7eSJed Brown /// * `interp_c_to_f` - Matrix for coarse to fine 17419df49d7eSJed Brown /// 17429df49d7eSJed Brown /// ``` 1743eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, EvalMode, MemType, QFunctionOpt, QuadMode, Scalar, TransposeMode, VectorOpt}; 17444d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 17459df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 17469df49d7eSJed Brown /// let ne = 15; 17479df49d7eSJed Brown /// let p_coarse = 3; 17489df49d7eSJed Brown /// let p_fine = 5; 17499df49d7eSJed Brown /// let q = 6; 17509df49d7eSJed Brown /// let ndofs_coarse = p_coarse * ne - ne + 1; 17519df49d7eSJed Brown /// let ndofs_fine = p_fine * ne - ne + 1; 17529df49d7eSJed Brown /// 17539df49d7eSJed Brown /// // Vectors 17549df49d7eSJed Brown /// let x_array = (0..ne + 1) 175580a9ef05SNatalie Beams /// .map(|i| 2.0 * i as Scalar / ne as Scalar - 1.0) 175680a9ef05SNatalie Beams /// .collect::<Vec<Scalar>>(); 1757c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&x_array)?; 1758c68be7a2SJeremy L Thompson /// let mut qdata = ceed.vector(ne * q)?; 17599df49d7eSJed Brown /// qdata.set_value(0.0); 1760c68be7a2SJeremy L Thompson /// let mut u_coarse = ceed.vector(ndofs_coarse)?; 17619df49d7eSJed Brown /// u_coarse.set_value(1.0); 1762c68be7a2SJeremy L Thompson /// let mut u_fine = ceed.vector(ndofs_fine)?; 17639df49d7eSJed Brown /// u_fine.set_value(1.0); 1764c68be7a2SJeremy L Thompson /// let mut v_coarse = ceed.vector(ndofs_coarse)?; 17659df49d7eSJed Brown /// v_coarse.set_value(0.0); 1766c68be7a2SJeremy L Thompson /// let mut v_fine = ceed.vector(ndofs_fine)?; 17679df49d7eSJed Brown /// v_fine.set_value(0.0); 1768c68be7a2SJeremy L Thompson /// let mut multiplicity = ceed.vector(ndofs_fine)?; 17699df49d7eSJed Brown /// multiplicity.set_value(1.0); 17709df49d7eSJed Brown /// 17719df49d7eSJed Brown /// // Restrictions 17729df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 1773c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 17749df49d7eSJed Brown /// 17759df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 17769df49d7eSJed Brown /// for i in 0..ne { 17779df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 17789df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 17799df49d7eSJed Brown /// } 1780c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 17819df49d7eSJed Brown /// 17829df49d7eSJed Brown /// let mut indu_coarse: Vec<i32> = vec![0; p_coarse * ne]; 17839df49d7eSJed Brown /// for i in 0..ne { 17849df49d7eSJed Brown /// for j in 0..p_coarse { 17859df49d7eSJed Brown /// indu_coarse[p_coarse * i + j] = (i + j) as i32; 17869df49d7eSJed Brown /// } 17879df49d7eSJed Brown /// } 1788c68be7a2SJeremy L Thompson /// let ru_coarse = ceed.elem_restriction( 17899df49d7eSJed Brown /// ne, 17909df49d7eSJed Brown /// p_coarse, 17919df49d7eSJed Brown /// 1, 17929df49d7eSJed Brown /// 1, 17939df49d7eSJed Brown /// ndofs_coarse, 17949df49d7eSJed Brown /// MemType::Host, 17959df49d7eSJed Brown /// &indu_coarse, 1796c68be7a2SJeremy L Thompson /// )?; 17979df49d7eSJed Brown /// 17989df49d7eSJed Brown /// let mut indu_fine: Vec<i32> = vec![0; p_fine * ne]; 17999df49d7eSJed Brown /// for i in 0..ne { 18009df49d7eSJed Brown /// for j in 0..p_fine { 18019df49d7eSJed Brown /// indu_fine[p_fine * i + j] = (i + j) as i32; 18029df49d7eSJed Brown /// } 18039df49d7eSJed Brown /// } 1804c68be7a2SJeremy L Thompson /// let ru_fine = ceed.elem_restriction(ne, p_fine, 1, 1, ndofs_fine, MemType::Host, &indu_fine)?; 18059df49d7eSJed Brown /// 18069df49d7eSJed Brown /// // Bases 1807c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 1808c68be7a2SJeremy L Thompson /// let bu_coarse = ceed.basis_tensor_H1_Lagrange(1, 1, p_coarse, q, QuadMode::Gauss)?; 1809c68be7a2SJeremy L Thompson /// let bu_fine = ceed.basis_tensor_H1_Lagrange(1, 1, p_fine, q, QuadMode::Gauss)?; 18109df49d7eSJed Brown /// 18119df49d7eSJed Brown /// // Build quadrature data 1812c68be7a2SJeremy L Thompson /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 1813c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 1814c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 1815c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 1816356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)? 1817c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata)?; 18189df49d7eSJed Brown /// 18199df49d7eSJed Brown /// // Mass operator 1820c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 18219df49d7eSJed Brown /// let op_mass_fine = ceed 1822c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 1823c68be7a2SJeremy L Thompson /// .field("u", &ru_fine, &bu_fine, VectorOpt::Active)? 1824356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, &qdata)? 1825c68be7a2SJeremy L Thompson /// .field("v", &ru_fine, &bu_fine, VectorOpt::Active)?; 18269df49d7eSJed Brown /// 18279df49d7eSJed Brown /// // Multigrid setup 182880a9ef05SNatalie Beams /// let mut interp_c_to_f: Vec<Scalar> = vec![0.; p_coarse * p_fine]; 18299df49d7eSJed Brown /// { 1830c68be7a2SJeremy L Thompson /// let mut coarse = ceed.vector(p_coarse)?; 1831c68be7a2SJeremy L Thompson /// let mut fine = ceed.vector(p_fine)?; 1832c68be7a2SJeremy L Thompson /// let basis_c_to_f = 1833c68be7a2SJeremy L Thompson /// ceed.basis_tensor_H1_Lagrange(1, 1, p_coarse, p_fine, QuadMode::GaussLobatto)?; 18349df49d7eSJed Brown /// for i in 0..p_coarse { 18359df49d7eSJed Brown /// coarse.set_value(0.0); 18369df49d7eSJed Brown /// { 1837e78171edSJeremy L Thompson /// let mut array = coarse.view_mut()?; 18389df49d7eSJed Brown /// array[i] = 1.; 18399df49d7eSJed Brown /// } 1840c68be7a2SJeremy L Thompson /// basis_c_to_f.apply( 18419df49d7eSJed Brown /// 1, 18429df49d7eSJed Brown /// TransposeMode::NoTranspose, 18439df49d7eSJed Brown /// EvalMode::Interp, 18449df49d7eSJed Brown /// &coarse, 18459df49d7eSJed Brown /// &mut fine, 1846c68be7a2SJeremy L Thompson /// )?; 1847e78171edSJeremy L Thompson /// let array = fine.view()?; 18489df49d7eSJed Brown /// for j in 0..p_fine { 18499df49d7eSJed Brown /// interp_c_to_f[j * p_coarse + i] = array[j]; 18509df49d7eSJed Brown /// } 18519df49d7eSJed Brown /// } 18529df49d7eSJed Brown /// } 1853c68be7a2SJeremy L Thompson /// let (op_mass_coarse, op_prolong, op_restrict) = op_mass_fine.create_multigrid_level_tensor_H1( 1854c68be7a2SJeremy L Thompson /// &multiplicity, 1855c68be7a2SJeremy L Thompson /// &ru_coarse, 1856c68be7a2SJeremy L Thompson /// &bu_coarse, 1857c68be7a2SJeremy L Thompson /// &interp_c_to_f, 1858c68be7a2SJeremy L Thompson /// )?; 18599df49d7eSJed Brown /// 18609df49d7eSJed Brown /// // Coarse problem 18619df49d7eSJed Brown /// u_coarse.set_value(1.0); 1862c68be7a2SJeremy L Thompson /// op_mass_coarse.apply(&u_coarse, &mut v_coarse)?; 18639df49d7eSJed Brown /// 18649df49d7eSJed Brown /// // Check 1865e78171edSJeremy L Thompson /// let sum: Scalar = v_coarse.view()?.iter().sum(); 18669df49d7eSJed Brown /// assert!( 186780a9ef05SNatalie Beams /// (sum - 2.0).abs() < 10.0 * libceed::EPSILON, 18689df49d7eSJed Brown /// "Incorrect interval length computed" 18699df49d7eSJed Brown /// ); 18709df49d7eSJed Brown /// 18719df49d7eSJed Brown /// // Prolong 1872c68be7a2SJeremy L Thompson /// op_prolong.apply(&u_coarse, &mut u_fine)?; 18739df49d7eSJed Brown /// 18749df49d7eSJed Brown /// // Fine problem 1875c68be7a2SJeremy L Thompson /// op_mass_fine.apply(&u_fine, &mut v_fine)?; 18769df49d7eSJed Brown /// 18779df49d7eSJed Brown /// // Check 1878e78171edSJeremy L Thompson /// let sum: Scalar = v_fine.view()?.iter().sum(); 18799df49d7eSJed Brown /// assert!( 1880392d940cSJeremy L Thompson /// (sum - 2.0).abs() < 200.0 * libceed::EPSILON, 18819df49d7eSJed Brown /// "Incorrect interval length computed" 18829df49d7eSJed Brown /// ); 18839df49d7eSJed Brown /// 18849df49d7eSJed Brown /// // Restrict 1885c68be7a2SJeremy L Thompson /// op_restrict.apply(&v_fine, &mut v_coarse)?; 18869df49d7eSJed Brown /// 18879df49d7eSJed Brown /// // Check 1888e78171edSJeremy L Thompson /// let sum: Scalar = v_coarse.view()?.iter().sum(); 18899df49d7eSJed Brown /// assert!( 1890392d940cSJeremy L Thompson /// (sum - 2.0).abs() < 200.0 * libceed::EPSILON, 18919df49d7eSJed Brown /// "Incorrect interval length computed" 18929df49d7eSJed Brown /// ); 1893c68be7a2SJeremy L Thompson /// # Ok(()) 1894c68be7a2SJeremy L Thompson /// # } 18959df49d7eSJed Brown /// ``` 1896594ef120SJeremy L Thompson pub fn create_multigrid_level_tensor_H1<'b>( 18979df49d7eSJed Brown &self, 18989df49d7eSJed Brown p_mult_fine: &Vector, 18999df49d7eSJed Brown rstr_coarse: &ElemRestriction, 19009df49d7eSJed Brown basis_coarse: &Basis, 19019ab2bffdSJeremy L Thompson interpCtoF: &[crate::Scalar], 1902594ef120SJeremy L Thompson ) -> crate::Result<(Operator<'b>, Operator<'b>, Operator<'b>)> { 19039df49d7eSJed Brown let mut ptr_coarse = std::ptr::null_mut(); 19049df49d7eSJed Brown let mut ptr_prolong = std::ptr::null_mut(); 19059df49d7eSJed Brown let mut ptr_restrict = std::ptr::null_mut(); 1906656ef1e5SJeremy L Thompson self.op_core.check_error(unsafe { 19079df49d7eSJed Brown bind_ceed::CeedOperatorMultigridLevelCreateTensorH1( 19089df49d7eSJed Brown self.op_core.ptr, 19099df49d7eSJed Brown p_mult_fine.ptr, 19109df49d7eSJed Brown rstr_coarse.ptr, 19119df49d7eSJed Brown basis_coarse.ptr, 19129df49d7eSJed Brown interpCtoF.as_ptr(), 19139df49d7eSJed Brown &mut ptr_coarse, 19149df49d7eSJed Brown &mut ptr_prolong, 19159df49d7eSJed Brown &mut ptr_restrict, 19169df49d7eSJed Brown ) 1917656ef1e5SJeremy L Thompson })?; 19182b671a0aSJeremy L Thompson let op_coarse = unsafe { Operator::from_raw(ptr_coarse)? }; 19192b671a0aSJeremy L Thompson let op_prolong = unsafe { Operator::from_raw(ptr_prolong)? }; 19202b671a0aSJeremy L Thompson let op_restrict = unsafe { Operator::from_raw(ptr_restrict)? }; 19219df49d7eSJed Brown Ok((op_coarse, op_prolong, op_restrict)) 19229df49d7eSJed Brown } 19239df49d7eSJed Brown 19249df49d7eSJed Brown /// Create a multigrid coarse Operator and level transfer Operators for a 19259df49d7eSJed Brown /// given Operator with a non-tensor basis for the active basis 19269df49d7eSJed Brown /// 19279df49d7eSJed Brown /// * `p_mult_fine` - Lvector multiplicity in parallel gather/scatter 19289df49d7eSJed Brown /// * `rstr_coarse` - Coarse grid restriction 19299df49d7eSJed Brown /// * `basis_coarse` - Coarse grid active vector basis 19309df49d7eSJed Brown /// * `interp_c_to_f` - Matrix for coarse to fine 19319df49d7eSJed Brown /// 19329df49d7eSJed Brown /// ``` 1933eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, EvalMode, MemType, QFunctionOpt, QuadMode, Scalar, TransposeMode, VectorOpt}; 19344d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 19359df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 19369df49d7eSJed Brown /// let ne = 15; 19379df49d7eSJed Brown /// let p_coarse = 3; 19389df49d7eSJed Brown /// let p_fine = 5; 19399df49d7eSJed Brown /// let q = 6; 19409df49d7eSJed Brown /// let ndofs_coarse = p_coarse * ne - ne + 1; 19419df49d7eSJed Brown /// let ndofs_fine = p_fine * ne - ne + 1; 19429df49d7eSJed Brown /// 19439df49d7eSJed Brown /// // Vectors 19449df49d7eSJed Brown /// let x_array = (0..ne + 1) 194580a9ef05SNatalie Beams /// .map(|i| 2.0 * i as Scalar / ne as Scalar - 1.0) 194680a9ef05SNatalie Beams /// .collect::<Vec<Scalar>>(); 1947c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&x_array)?; 1948c68be7a2SJeremy L Thompson /// let mut qdata = ceed.vector(ne * q)?; 19499df49d7eSJed Brown /// qdata.set_value(0.0); 1950c68be7a2SJeremy L Thompson /// let mut u_coarse = ceed.vector(ndofs_coarse)?; 19519df49d7eSJed Brown /// u_coarse.set_value(1.0); 1952c68be7a2SJeremy L Thompson /// let mut u_fine = ceed.vector(ndofs_fine)?; 19539df49d7eSJed Brown /// u_fine.set_value(1.0); 1954c68be7a2SJeremy L Thompson /// let mut v_coarse = ceed.vector(ndofs_coarse)?; 19559df49d7eSJed Brown /// v_coarse.set_value(0.0); 1956c68be7a2SJeremy L Thompson /// let mut v_fine = ceed.vector(ndofs_fine)?; 19579df49d7eSJed Brown /// v_fine.set_value(0.0); 1958c68be7a2SJeremy L Thompson /// let mut multiplicity = ceed.vector(ndofs_fine)?; 19599df49d7eSJed Brown /// multiplicity.set_value(1.0); 19609df49d7eSJed Brown /// 19619df49d7eSJed Brown /// // Restrictions 19629df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 1963c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 19649df49d7eSJed Brown /// 19659df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 19669df49d7eSJed Brown /// for i in 0..ne { 19679df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 19689df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 19699df49d7eSJed Brown /// } 1970c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 19719df49d7eSJed Brown /// 19729df49d7eSJed Brown /// let mut indu_coarse: Vec<i32> = vec![0; p_coarse * ne]; 19739df49d7eSJed Brown /// for i in 0..ne { 19749df49d7eSJed Brown /// for j in 0..p_coarse { 19759df49d7eSJed Brown /// indu_coarse[p_coarse * i + j] = (i + j) as i32; 19769df49d7eSJed Brown /// } 19779df49d7eSJed Brown /// } 1978c68be7a2SJeremy L Thompson /// let ru_coarse = ceed.elem_restriction( 19799df49d7eSJed Brown /// ne, 19809df49d7eSJed Brown /// p_coarse, 19819df49d7eSJed Brown /// 1, 19829df49d7eSJed Brown /// 1, 19839df49d7eSJed Brown /// ndofs_coarse, 19849df49d7eSJed Brown /// MemType::Host, 19859df49d7eSJed Brown /// &indu_coarse, 1986c68be7a2SJeremy L Thompson /// )?; 19879df49d7eSJed Brown /// 19889df49d7eSJed Brown /// let mut indu_fine: Vec<i32> = vec![0; p_fine * ne]; 19899df49d7eSJed Brown /// for i in 0..ne { 19909df49d7eSJed Brown /// for j in 0..p_fine { 19919df49d7eSJed Brown /// indu_fine[p_fine * i + j] = (i + j) as i32; 19929df49d7eSJed Brown /// } 19939df49d7eSJed Brown /// } 1994c68be7a2SJeremy L Thompson /// let ru_fine = ceed.elem_restriction(ne, p_fine, 1, 1, ndofs_fine, MemType::Host, &indu_fine)?; 19959df49d7eSJed Brown /// 19969df49d7eSJed Brown /// // Bases 1997c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 1998c68be7a2SJeremy L Thompson /// let bu_coarse = ceed.basis_tensor_H1_Lagrange(1, 1, p_coarse, q, QuadMode::Gauss)?; 1999c68be7a2SJeremy L Thompson /// let bu_fine = ceed.basis_tensor_H1_Lagrange(1, 1, p_fine, q, QuadMode::Gauss)?; 20009df49d7eSJed Brown /// 20019df49d7eSJed Brown /// // Build quadrature data 2002c68be7a2SJeremy L Thompson /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 2003c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 2004c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 2005c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 2006356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)? 2007c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata)?; 20089df49d7eSJed Brown /// 20099df49d7eSJed Brown /// // Mass operator 2010c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 20119df49d7eSJed Brown /// let op_mass_fine = ceed 2012c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 2013c68be7a2SJeremy L Thompson /// .field("u", &ru_fine, &bu_fine, VectorOpt::Active)? 2014356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, &qdata)? 2015c68be7a2SJeremy L Thompson /// .field("v", &ru_fine, &bu_fine, VectorOpt::Active)?; 20169df49d7eSJed Brown /// 20179df49d7eSJed Brown /// // Multigrid setup 201880a9ef05SNatalie Beams /// let mut interp_c_to_f: Vec<Scalar> = vec![0.; p_coarse * p_fine]; 20199df49d7eSJed Brown /// { 2020c68be7a2SJeremy L Thompson /// let mut coarse = ceed.vector(p_coarse)?; 2021c68be7a2SJeremy L Thompson /// let mut fine = ceed.vector(p_fine)?; 2022c68be7a2SJeremy L Thompson /// let basis_c_to_f = 2023c68be7a2SJeremy L Thompson /// ceed.basis_tensor_H1_Lagrange(1, 1, p_coarse, p_fine, QuadMode::GaussLobatto)?; 20249df49d7eSJed Brown /// for i in 0..p_coarse { 20259df49d7eSJed Brown /// coarse.set_value(0.0); 20269df49d7eSJed Brown /// { 2027e78171edSJeremy L Thompson /// let mut array = coarse.view_mut()?; 20289df49d7eSJed Brown /// array[i] = 1.; 20299df49d7eSJed Brown /// } 2030c68be7a2SJeremy L Thompson /// basis_c_to_f.apply( 20319df49d7eSJed Brown /// 1, 20329df49d7eSJed Brown /// TransposeMode::NoTranspose, 20339df49d7eSJed Brown /// EvalMode::Interp, 20349df49d7eSJed Brown /// &coarse, 20359df49d7eSJed Brown /// &mut fine, 2036c68be7a2SJeremy L Thompson /// )?; 2037e78171edSJeremy L Thompson /// let array = fine.view()?; 20389df49d7eSJed Brown /// for j in 0..p_fine { 20399df49d7eSJed Brown /// interp_c_to_f[j * p_coarse + i] = array[j]; 20409df49d7eSJed Brown /// } 20419df49d7eSJed Brown /// } 20429df49d7eSJed Brown /// } 2043c68be7a2SJeremy L Thompson /// let (op_mass_coarse, op_prolong, op_restrict) = op_mass_fine.create_multigrid_level_H1( 2044c68be7a2SJeremy L Thompson /// &multiplicity, 2045c68be7a2SJeremy L Thompson /// &ru_coarse, 2046c68be7a2SJeremy L Thompson /// &bu_coarse, 2047c68be7a2SJeremy L Thompson /// &interp_c_to_f, 2048c68be7a2SJeremy L Thompson /// )?; 20499df49d7eSJed Brown /// 20509df49d7eSJed Brown /// // Coarse problem 20519df49d7eSJed Brown /// u_coarse.set_value(1.0); 2052c68be7a2SJeremy L Thompson /// op_mass_coarse.apply(&u_coarse, &mut v_coarse)?; 20539df49d7eSJed Brown /// 20549df49d7eSJed Brown /// // Check 2055e78171edSJeremy L Thompson /// let sum: Scalar = v_coarse.view()?.iter().sum(); 20569df49d7eSJed Brown /// assert!( 205780a9ef05SNatalie Beams /// (sum - 2.0).abs() < 10.0 * libceed::EPSILON, 20589df49d7eSJed Brown /// "Incorrect interval length computed" 20599df49d7eSJed Brown /// ); 20609df49d7eSJed Brown /// 20619df49d7eSJed Brown /// // Prolong 2062c68be7a2SJeremy L Thompson /// op_prolong.apply(&u_coarse, &mut u_fine)?; 20639df49d7eSJed Brown /// 20649df49d7eSJed Brown /// // Fine problem 2065c68be7a2SJeremy L Thompson /// op_mass_fine.apply(&u_fine, &mut v_fine)?; 20669df49d7eSJed Brown /// 20679df49d7eSJed Brown /// // Check 2068e78171edSJeremy L Thompson /// let sum: Scalar = v_fine.view()?.iter().sum(); 20699df49d7eSJed Brown /// assert!( 2070392d940cSJeremy L Thompson /// (sum - 2.0).abs() < 200.0 * libceed::EPSILON, 20719df49d7eSJed Brown /// "Incorrect interval length computed" 20729df49d7eSJed Brown /// ); 20739df49d7eSJed Brown /// 20749df49d7eSJed Brown /// // Restrict 2075c68be7a2SJeremy L Thompson /// op_restrict.apply(&v_fine, &mut v_coarse)?; 20769df49d7eSJed Brown /// 20779df49d7eSJed Brown /// // Check 2078e78171edSJeremy L Thompson /// let sum: Scalar = v_coarse.view()?.iter().sum(); 20799df49d7eSJed Brown /// assert!( 2080392d940cSJeremy L Thompson /// (sum - 2.0).abs() < 200.0 * libceed::EPSILON, 20819df49d7eSJed Brown /// "Incorrect interval length computed" 20829df49d7eSJed Brown /// ); 2083c68be7a2SJeremy L Thompson /// # Ok(()) 2084c68be7a2SJeremy L Thompson /// # } 20859df49d7eSJed Brown /// ``` 2086594ef120SJeremy L Thompson pub fn create_multigrid_level_H1<'b>( 20879df49d7eSJed Brown &self, 20889df49d7eSJed Brown p_mult_fine: &Vector, 20899df49d7eSJed Brown rstr_coarse: &ElemRestriction, 20909df49d7eSJed Brown basis_coarse: &Basis, 2091eb07d68fSJeremy L Thompson interpCtoF: &[crate::Scalar], 2092594ef120SJeremy L Thompson ) -> crate::Result<(Operator<'b>, Operator<'b>, Operator<'b>)> { 20939df49d7eSJed Brown let mut ptr_coarse = std::ptr::null_mut(); 20949df49d7eSJed Brown let mut ptr_prolong = std::ptr::null_mut(); 20959df49d7eSJed Brown let mut ptr_restrict = std::ptr::null_mut(); 2096656ef1e5SJeremy L Thompson self.op_core.check_error(unsafe { 20979df49d7eSJed Brown bind_ceed::CeedOperatorMultigridLevelCreateH1( 20989df49d7eSJed Brown self.op_core.ptr, 20999df49d7eSJed Brown p_mult_fine.ptr, 21009df49d7eSJed Brown rstr_coarse.ptr, 21019df49d7eSJed Brown basis_coarse.ptr, 21029df49d7eSJed Brown interpCtoF.as_ptr(), 21039df49d7eSJed Brown &mut ptr_coarse, 21049df49d7eSJed Brown &mut ptr_prolong, 21059df49d7eSJed Brown &mut ptr_restrict, 21069df49d7eSJed Brown ) 2107656ef1e5SJeremy L Thompson })?; 21082b671a0aSJeremy L Thompson let op_coarse = unsafe { Operator::from_raw(ptr_coarse)? }; 21092b671a0aSJeremy L Thompson let op_prolong = unsafe { Operator::from_raw(ptr_prolong)? }; 21102b671a0aSJeremy L Thompson let op_restrict = unsafe { Operator::from_raw(ptr_restrict)? }; 21119df49d7eSJed Brown Ok((op_coarse, op_prolong, op_restrict)) 21129df49d7eSJed Brown } 21139df49d7eSJed Brown } 21149df49d7eSJed Brown 21159df49d7eSJed Brown // ----------------------------------------------------------------------------- 21169df49d7eSJed Brown // Composite Operator 21179df49d7eSJed Brown // ----------------------------------------------------------------------------- 21189df49d7eSJed Brown impl<'a> CompositeOperator<'a> { 21199df49d7eSJed Brown // Constructor 2120594ef120SJeremy L Thompson pub fn create(ceed: &crate::Ceed) -> crate::Result<Self> { 21219df49d7eSJed Brown let mut ptr = std::ptr::null_mut(); 2122ed094490SJeremy L Thompson ceed.check_error(unsafe { bind_ceed::CeedOperatorCreateComposite(ceed.ptr, &mut ptr) })?; 21239df49d7eSJed Brown Ok(Self { 21241142270cSJeremy L Thompson op_core: OperatorCore { 21251142270cSJeremy L Thompson ptr, 21261142270cSJeremy L Thompson _lifeline: PhantomData, 21271142270cSJeremy L Thompson }, 21289df49d7eSJed Brown }) 21299df49d7eSJed Brown } 21309df49d7eSJed Brown 2131ea6b5821SJeremy L Thompson /// Set name for CompositeOperator printing 2132ea6b5821SJeremy L Thompson /// 2133ea6b5821SJeremy L Thompson /// * 'name' - Name to set 2134ea6b5821SJeremy L Thompson /// 2135ea6b5821SJeremy L Thompson /// ``` 2136eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, MemType, QFunctionOpt, QuadMode, VectorOpt}; 2137ea6b5821SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 2138ea6b5821SJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 2139ea6b5821SJeremy L Thompson /// 2140ea6b5821SJeremy L Thompson /// // Sub operator field arguments 2141ea6b5821SJeremy L Thompson /// let ne = 3; 2142bf55b007SJeremy L Thompson /// let q = 4_usize; 2143ea6b5821SJeremy L Thompson /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 2144ea6b5821SJeremy L Thompson /// for i in 0..ne { 2145ea6b5821SJeremy L Thompson /// ind[2 * i + 0] = i as i32; 2146ea6b5821SJeremy L Thompson /// ind[2 * i + 1] = (i + 1) as i32; 2147ea6b5821SJeremy L Thompson /// } 2148ea6b5821SJeremy L Thompson /// let r = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind)?; 2149ea6b5821SJeremy L Thompson /// let strides: [i32; 3] = [1, q as i32, q as i32]; 2150d9267b76SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 2151ea6b5821SJeremy L Thompson /// 2152ea6b5821SJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 2153ea6b5821SJeremy L Thompson /// 2154ea6b5821SJeremy L Thompson /// let qdata_mass = ceed.vector(q * ne)?; 2155ea6b5821SJeremy L Thompson /// let qdata_diff = ceed.vector(q * ne)?; 2156ea6b5821SJeremy L Thompson /// 2157ea6b5821SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 2158ea6b5821SJeremy L Thompson /// let op_mass = ceed 2159ea6b5821SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 2160ea6b5821SJeremy L Thompson /// .name("Mass term")? 2161ea6b5821SJeremy L Thompson /// .field("u", &r, &b, VectorOpt::Active)? 2162356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, &qdata_mass)? 2163ea6b5821SJeremy L Thompson /// .field("v", &r, &b, VectorOpt::Active)?; 2164ea6b5821SJeremy L Thompson /// 2165ea6b5821SJeremy L Thompson /// let qf_diff = ceed.q_function_interior_by_name("Poisson1DApply")?; 2166ea6b5821SJeremy L Thompson /// let op_diff = ceed 2167ea6b5821SJeremy L Thompson /// .operator(&qf_diff, QFunctionOpt::None, QFunctionOpt::None)? 2168ea6b5821SJeremy L Thompson /// .name("Poisson term")? 2169ea6b5821SJeremy L Thompson /// .field("du", &r, &b, VectorOpt::Active)? 2170356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, &qdata_diff)? 2171ea6b5821SJeremy L Thompson /// .field("dv", &r, &b, VectorOpt::Active)?; 2172ea6b5821SJeremy L Thompson /// 2173ea6b5821SJeremy L Thompson /// let op = ceed 2174ea6b5821SJeremy L Thompson /// .composite_operator()? 2175ea6b5821SJeremy L Thompson /// .name("Screened Poisson")? 2176ea6b5821SJeremy L Thompson /// .sub_operator(&op_mass)? 2177ea6b5821SJeremy L Thompson /// .sub_operator(&op_diff)?; 2178ea6b5821SJeremy L Thompson /// # Ok(()) 2179ea6b5821SJeremy L Thompson /// # } 2180ea6b5821SJeremy L Thompson /// ``` 2181ea6b5821SJeremy L Thompson #[allow(unused_mut)] 2182ea6b5821SJeremy L Thompson pub fn name(mut self, name: &str) -> crate::Result<Self> { 2183ea6b5821SJeremy L Thompson self.op_core.name(name)?; 2184ea6b5821SJeremy L Thompson Ok(self) 2185ea6b5821SJeremy L Thompson } 2186ea6b5821SJeremy L Thompson 21879df49d7eSJed Brown /// Apply Operator to a vector 21889df49d7eSJed Brown /// 2189ea6b5821SJeremy L Thompson /// * `input` - Inpuht Vector 21909df49d7eSJed Brown /// * `output` - Output Vector 21919df49d7eSJed Brown /// 21929df49d7eSJed Brown /// ``` 2193eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, MemType, QFunctionOpt, QuadMode, Scalar, VectorOpt}; 21944d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 21959df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 21969df49d7eSJed Brown /// let ne = 4; 21979df49d7eSJed Brown /// let p = 3; 21989df49d7eSJed Brown /// let q = 4; 21999df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 22009df49d7eSJed Brown /// 22019df49d7eSJed Brown /// // Vectors 2202c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0])?; 2203c68be7a2SJeremy L Thompson /// let mut qdata_mass = ceed.vector(ne * q)?; 22049df49d7eSJed Brown /// qdata_mass.set_value(0.0); 2205c68be7a2SJeremy L Thompson /// let mut qdata_diff = ceed.vector(ne * q)?; 22069df49d7eSJed Brown /// qdata_diff.set_value(0.0); 2207c68be7a2SJeremy L Thompson /// let mut u = ceed.vector(ndofs)?; 22089df49d7eSJed Brown /// u.set_value(1.0); 2209c68be7a2SJeremy L Thompson /// let mut v = ceed.vector(ndofs)?; 22109df49d7eSJed Brown /// v.set_value(0.0); 22119df49d7eSJed Brown /// 22129df49d7eSJed Brown /// // Restrictions 22139df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 22149df49d7eSJed Brown /// for i in 0..ne { 22159df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 22169df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 22179df49d7eSJed Brown /// } 2218c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 22199df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 22209df49d7eSJed Brown /// for i in 0..ne { 22219df49d7eSJed Brown /// indu[p * i + 0] = i as i32; 22229df49d7eSJed Brown /// indu[p * i + 1] = (i + 1) as i32; 22239df49d7eSJed Brown /// indu[p * i + 2] = (i + 2) as i32; 22249df49d7eSJed Brown /// } 2225c68be7a2SJeremy L Thompson /// let ru = ceed.elem_restriction(ne, 3, 1, 1, ndofs, MemType::Host, &indu)?; 22269df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 2227c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 22289df49d7eSJed Brown /// 22299df49d7eSJed Brown /// // Bases 2230c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 2231c68be7a2SJeremy L Thompson /// let bu = ceed.basis_tensor_H1_Lagrange(1, 1, p, q, QuadMode::Gauss)?; 22329df49d7eSJed Brown /// 22339df49d7eSJed Brown /// // Build quadrature data 2234c68be7a2SJeremy L Thompson /// let qf_build_mass = ceed.q_function_interior_by_name("Mass1DBuild")?; 2235c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build_mass, QFunctionOpt::None, QFunctionOpt::None)? 2236c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 2237c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 2238356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)? 2239c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata_mass)?; 22409df49d7eSJed Brown /// 2241c68be7a2SJeremy L Thompson /// let qf_build_diff = ceed.q_function_interior_by_name("Poisson1DBuild")?; 2242c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build_diff, QFunctionOpt::None, QFunctionOpt::None)? 2243c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 2244c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 2245356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)? 2246c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata_diff)?; 22479df49d7eSJed Brown /// 22489df49d7eSJed Brown /// // Application operator 2249c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 22509df49d7eSJed Brown /// let op_mass = ceed 2251c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 2252c68be7a2SJeremy L Thompson /// .field("u", &ru, &bu, VectorOpt::Active)? 2253356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, &qdata_mass)? 2254c68be7a2SJeremy L Thompson /// .field("v", &ru, &bu, VectorOpt::Active)?; 22559df49d7eSJed Brown /// 2256c68be7a2SJeremy L Thompson /// let qf_diff = ceed.q_function_interior_by_name("Poisson1DApply")?; 22579df49d7eSJed Brown /// let op_diff = ceed 2258c68be7a2SJeremy L Thompson /// .operator(&qf_diff, QFunctionOpt::None, QFunctionOpt::None)? 2259c68be7a2SJeremy L Thompson /// .field("du", &ru, &bu, VectorOpt::Active)? 2260356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, &qdata_diff)? 2261c68be7a2SJeremy L Thompson /// .field("dv", &ru, &bu, VectorOpt::Active)?; 22629df49d7eSJed Brown /// 22639df49d7eSJed Brown /// let op_composite = ceed 2264c68be7a2SJeremy L Thompson /// .composite_operator()? 2265c68be7a2SJeremy L Thompson /// .sub_operator(&op_mass)? 2266c68be7a2SJeremy L Thompson /// .sub_operator(&op_diff)?; 22679df49d7eSJed Brown /// 22689df49d7eSJed Brown /// v.set_value(0.0); 2269c68be7a2SJeremy L Thompson /// op_composite.apply(&u, &mut v)?; 22709df49d7eSJed Brown /// 22719df49d7eSJed Brown /// // Check 2272e78171edSJeremy L Thompson /// let sum: Scalar = v.view()?.iter().sum(); 22739df49d7eSJed Brown /// assert!( 227480a9ef05SNatalie Beams /// (sum - 2.0).abs() < 10.0 * libceed::EPSILON, 22759df49d7eSJed Brown /// "Incorrect interval length computed" 22769df49d7eSJed Brown /// ); 2277c68be7a2SJeremy L Thompson /// # Ok(()) 2278c68be7a2SJeremy L Thompson /// # } 22799df49d7eSJed Brown /// ``` 22809df49d7eSJed Brown pub fn apply(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> { 22819df49d7eSJed Brown self.op_core.apply(input, output) 22829df49d7eSJed Brown } 22839df49d7eSJed Brown 22849df49d7eSJed Brown /// Apply Operator to a vector and add result to output vector 22859df49d7eSJed Brown /// 22869df49d7eSJed Brown /// * `input` - Input Vector 22879df49d7eSJed Brown /// * `output` - Output Vector 22889df49d7eSJed Brown /// 22899df49d7eSJed Brown /// ``` 2290eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, MemType, QFunctionOpt, QuadMode, Scalar, VectorOpt}; 22914d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 22929df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 22939df49d7eSJed Brown /// let ne = 4; 22949df49d7eSJed Brown /// let p = 3; 22959df49d7eSJed Brown /// let q = 4; 22969df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 22979df49d7eSJed Brown /// 22989df49d7eSJed Brown /// // Vectors 2299c68be7a2SJeremy L Thompson /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0])?; 2300c68be7a2SJeremy L Thompson /// let mut qdata_mass = ceed.vector(ne * q)?; 23019df49d7eSJed Brown /// qdata_mass.set_value(0.0); 2302c68be7a2SJeremy L Thompson /// let mut qdata_diff = ceed.vector(ne * q)?; 23039df49d7eSJed Brown /// qdata_diff.set_value(0.0); 2304c68be7a2SJeremy L Thompson /// let mut u = ceed.vector(ndofs)?; 23059df49d7eSJed Brown /// u.set_value(1.0); 2306c68be7a2SJeremy L Thompson /// let mut v = ceed.vector(ndofs)?; 23079df49d7eSJed Brown /// v.set_value(0.0); 23089df49d7eSJed Brown /// 23099df49d7eSJed Brown /// // Restrictions 23109df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 23119df49d7eSJed Brown /// for i in 0..ne { 23129df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 23139df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 23149df49d7eSJed Brown /// } 2315c68be7a2SJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 23169df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 23179df49d7eSJed Brown /// for i in 0..ne { 23189df49d7eSJed Brown /// indu[p * i + 0] = i as i32; 23199df49d7eSJed Brown /// indu[p * i + 1] = (i + 1) as i32; 23209df49d7eSJed Brown /// indu[p * i + 2] = (i + 2) as i32; 23219df49d7eSJed Brown /// } 2322c68be7a2SJeremy L Thompson /// let ru = ceed.elem_restriction(ne, 3, 1, 1, ndofs, MemType::Host, &indu)?; 23239df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 2324c68be7a2SJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 23259df49d7eSJed Brown /// 23269df49d7eSJed Brown /// // Bases 2327c68be7a2SJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 2328c68be7a2SJeremy L Thompson /// let bu = ceed.basis_tensor_H1_Lagrange(1, 1, p, q, QuadMode::Gauss)?; 23299df49d7eSJed Brown /// 23309df49d7eSJed Brown /// // Build quadrature data 2331c68be7a2SJeremy L Thompson /// let qf_build_mass = ceed.q_function_interior_by_name("Mass1DBuild")?; 2332c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build_mass, QFunctionOpt::None, QFunctionOpt::None)? 2333c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 2334c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 2335356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)? 2336c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata_mass)?; 23379df49d7eSJed Brown /// 2338c68be7a2SJeremy L Thompson /// let qf_build_diff = ceed.q_function_interior_by_name("Poisson1DBuild")?; 2339c68be7a2SJeremy L Thompson /// ceed.operator(&qf_build_diff, QFunctionOpt::None, QFunctionOpt::None)? 2340c68be7a2SJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 2341c68be7a2SJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 2342356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)? 2343c68be7a2SJeremy L Thompson /// .apply(&x, &mut qdata_diff)?; 23449df49d7eSJed Brown /// 23459df49d7eSJed Brown /// // Application operator 2346c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 23479df49d7eSJed Brown /// let op_mass = ceed 2348c68be7a2SJeremy L Thompson /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 2349c68be7a2SJeremy L Thompson /// .field("u", &ru, &bu, VectorOpt::Active)? 2350356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, &qdata_mass)? 2351c68be7a2SJeremy L Thompson /// .field("v", &ru, &bu, VectorOpt::Active)?; 23529df49d7eSJed Brown /// 2353c68be7a2SJeremy L Thompson /// let qf_diff = ceed.q_function_interior_by_name("Poisson1DApply")?; 23549df49d7eSJed Brown /// let op_diff = ceed 2355c68be7a2SJeremy L Thompson /// .operator(&qf_diff, QFunctionOpt::None, QFunctionOpt::None)? 2356c68be7a2SJeremy L Thompson /// .field("du", &ru, &bu, VectorOpt::Active)? 2357356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, &qdata_diff)? 2358c68be7a2SJeremy L Thompson /// .field("dv", &ru, &bu, VectorOpt::Active)?; 23599df49d7eSJed Brown /// 23609df49d7eSJed Brown /// let op_composite = ceed 2361c68be7a2SJeremy L Thompson /// .composite_operator()? 2362c68be7a2SJeremy L Thompson /// .sub_operator(&op_mass)? 2363c68be7a2SJeremy L Thompson /// .sub_operator(&op_diff)?; 23649df49d7eSJed Brown /// 23659df49d7eSJed Brown /// v.set_value(1.0); 2366c68be7a2SJeremy L Thompson /// op_composite.apply_add(&u, &mut v)?; 23679df49d7eSJed Brown /// 23689df49d7eSJed Brown /// // Check 2369e78171edSJeremy L Thompson /// let sum: Scalar = v.view()?.iter().sum(); 23709df49d7eSJed Brown /// assert!( 237180a9ef05SNatalie Beams /// (sum - (2.0 + ndofs as Scalar)).abs() < 10.0 * libceed::EPSILON, 23729df49d7eSJed Brown /// "Incorrect interval length computed" 23739df49d7eSJed Brown /// ); 2374c68be7a2SJeremy L Thompson /// # Ok(()) 2375c68be7a2SJeremy L Thompson /// # } 23769df49d7eSJed Brown /// ``` 23779df49d7eSJed Brown pub fn apply_add(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> { 23789df49d7eSJed Brown self.op_core.apply_add(input, output) 23799df49d7eSJed Brown } 23809df49d7eSJed Brown 23819df49d7eSJed Brown /// Add a sub-Operator to a Composite Operator 23829df49d7eSJed Brown /// 23839df49d7eSJed Brown /// * `subop` - Sub-Operator 23849df49d7eSJed Brown /// 23859df49d7eSJed Brown /// ``` 2386eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, QFunctionOpt}; 23874d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 23889df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 2389c68be7a2SJeremy L Thompson /// let mut op = ceed.composite_operator()?; 23909df49d7eSJed Brown /// 2391c68be7a2SJeremy L Thompson /// let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 2392c68be7a2SJeremy L Thompson /// let op_mass = ceed.operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)?; 2393c68be7a2SJeremy L Thompson /// op = op.sub_operator(&op_mass)?; 23949df49d7eSJed Brown /// 2395c68be7a2SJeremy L Thompson /// let qf_diff = ceed.q_function_interior_by_name("Poisson1DApply")?; 2396c68be7a2SJeremy L Thompson /// let op_diff = ceed.operator(&qf_diff, QFunctionOpt::None, QFunctionOpt::None)?; 2397c68be7a2SJeremy L Thompson /// op = op.sub_operator(&op_diff)?; 2398c68be7a2SJeremy L Thompson /// # Ok(()) 2399c68be7a2SJeremy L Thompson /// # } 24009df49d7eSJed Brown /// ``` 24019df49d7eSJed Brown #[allow(unused_mut)] 24029df49d7eSJed Brown pub fn sub_operator(mut self, subop: &Operator) -> crate::Result<Self> { 2403656ef1e5SJeremy L Thompson self.op_core.check_error(unsafe { 2404ed094490SJeremy L Thompson bind_ceed::CeedOperatorCompositeAddSub(self.op_core.ptr, subop.op_core.ptr) 2405656ef1e5SJeremy L Thompson })?; 24069df49d7eSJed Brown Ok(self) 24079df49d7eSJed Brown } 24089df49d7eSJed Brown 24096f97ff0aSJeremy L Thompson /// Check if CompositeOperator is setup correctly 24106f97ff0aSJeremy L Thompson /// 24116f97ff0aSJeremy L Thompson /// ``` 2412eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, BasisOpt, ElemRestrictionOpt, MemType, QFunctionOpt, QuadMode, VectorOpt}; 24136f97ff0aSJeremy L Thompson /// # fn main() -> libceed::Result<()> { 24146f97ff0aSJeremy L Thompson /// # let ceed = libceed::Ceed::default_init(); 24156f97ff0aSJeremy L Thompson /// let ne = 4; 24166f97ff0aSJeremy L Thompson /// let p = 3; 24176f97ff0aSJeremy L Thompson /// let q = 4; 24186f97ff0aSJeremy L Thompson /// let ndofs = p * ne - ne + 1; 24196f97ff0aSJeremy L Thompson /// 24206f97ff0aSJeremy L Thompson /// // Restrictions 24216f97ff0aSJeremy L Thompson /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 24226f97ff0aSJeremy L Thompson /// for i in 0..ne { 24236f97ff0aSJeremy L Thompson /// indx[2 * i + 0] = i as i32; 24246f97ff0aSJeremy L Thompson /// indx[2 * i + 1] = (i + 1) as i32; 24256f97ff0aSJeremy L Thompson /// } 24266f97ff0aSJeremy L Thompson /// let rx = ceed.elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx)?; 24276f97ff0aSJeremy L Thompson /// let strides: [i32; 3] = [1, q as i32, q as i32]; 24286f97ff0aSJeremy L Thompson /// let rq = ceed.strided_elem_restriction(ne, q, 1, q * ne, strides)?; 24296f97ff0aSJeremy L Thompson /// 24306f97ff0aSJeremy L Thompson /// // Bases 24316f97ff0aSJeremy L Thompson /// let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 24326f97ff0aSJeremy L Thompson /// 24336f97ff0aSJeremy L Thompson /// // Build quadrature data 24346f97ff0aSJeremy L Thompson /// let qf_build_mass = ceed.q_function_interior_by_name("Mass1DBuild")?; 24356f97ff0aSJeremy L Thompson /// let op_build_mass = ceed 24366f97ff0aSJeremy L Thompson /// .operator(&qf_build_mass, QFunctionOpt::None, QFunctionOpt::None)? 24376f97ff0aSJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 24386f97ff0aSJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 2439356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)?; 24406f97ff0aSJeremy L Thompson /// 24416f97ff0aSJeremy L Thompson /// let qf_build_diff = ceed.q_function_interior_by_name("Poisson1DBuild")?; 24426f97ff0aSJeremy L Thompson /// let op_build_diff = ceed 24436f97ff0aSJeremy L Thompson /// .operator(&qf_build_diff, QFunctionOpt::None, QFunctionOpt::None)? 24446f97ff0aSJeremy L Thompson /// .field("dx", &rx, &bx, VectorOpt::Active)? 24456f97ff0aSJeremy L Thompson /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 2446356036faSJeremy L Thompson /// .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)?; 24476f97ff0aSJeremy L Thompson /// 24486f97ff0aSJeremy L Thompson /// let op_build = ceed 24496f97ff0aSJeremy L Thompson /// .composite_operator()? 24506f97ff0aSJeremy L Thompson /// .sub_operator(&op_build_mass)? 24516f97ff0aSJeremy L Thompson /// .sub_operator(&op_build_diff)?; 24526f97ff0aSJeremy L Thompson /// 24536f97ff0aSJeremy L Thompson /// // Check 24546f97ff0aSJeremy L Thompson /// assert!(op_build.check().is_ok(), "Operator setup incorrectly"); 24556f97ff0aSJeremy L Thompson /// # Ok(()) 24566f97ff0aSJeremy L Thompson /// # } 24576f97ff0aSJeremy L Thompson /// ``` 24586f97ff0aSJeremy L Thompson pub fn check(self) -> crate::Result<Self> { 24596f97ff0aSJeremy L Thompson self.op_core.check()?; 24606f97ff0aSJeremy L Thompson Ok(self) 24616f97ff0aSJeremy L Thompson } 24626f97ff0aSJeremy L Thompson 24639df49d7eSJed Brown /// Assemble the diagonal of a square linear Operator 24649df49d7eSJed Brown /// 24659df49d7eSJed Brown /// This overwrites a Vector with the diagonal of a linear Operator. 24669df49d7eSJed Brown /// 24679df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 24689df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 24699df49d7eSJed Brown /// 24709df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 24719df49d7eSJed Brown /// * `assembled` - Vector to store assembled Operator diagonal 2472b748b478SJeremy L Thompson pub fn linear_assemble_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> { 24739df49d7eSJed Brown self.op_core.linear_assemble_add_diagonal(assembled) 24749df49d7eSJed Brown } 24759df49d7eSJed Brown 24769df49d7eSJed Brown /// Assemble the point block diagonal of a square linear Operator 24779df49d7eSJed Brown /// 24789df49d7eSJed Brown /// This overwrites a Vector with the point block diagonal of a linear 24799df49d7eSJed Brown /// Operator. 24809df49d7eSJed Brown /// 24819df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 24829df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 24839df49d7eSJed Brown /// 24849df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 24859df49d7eSJed Brown /// * `assembled` - Vector to store assembled Operator diagonal 24869df49d7eSJed Brown pub fn linear_assemble_add_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> { 24879df49d7eSJed Brown self.op_core.linear_assemble_add_diagonal(assembled) 24889df49d7eSJed Brown } 24899df49d7eSJed Brown 24909df49d7eSJed Brown /// Assemble the diagonal of a square linear Operator 24919df49d7eSJed Brown /// 24929df49d7eSJed Brown /// This overwrites a Vector with the diagonal of a linear Operator. 24939df49d7eSJed Brown /// 24949df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 24959df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 24969df49d7eSJed Brown /// 24979df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 24989df49d7eSJed Brown /// * `assembled` - Vector to store assembled CeedOperator point block 24999df49d7eSJed Brown /// diagonal, provided in row-major form with an 25009df49d7eSJed Brown /// `ncomp * ncomp` block at each node. The dimensions of 25019df49d7eSJed Brown /// this vector are derived from the active vector for 25029df49d7eSJed Brown /// the CeedOperator. The array has shape 25039df49d7eSJed Brown /// `[nodes, component out, component in]`. 25049df49d7eSJed Brown pub fn linear_assemble_point_block_diagonal( 25059df49d7eSJed Brown &self, 25069df49d7eSJed Brown assembled: &mut Vector, 25079df49d7eSJed Brown ) -> crate::Result<i32> { 25089df49d7eSJed Brown self.op_core.linear_assemble_add_diagonal(assembled) 25099df49d7eSJed Brown } 25109df49d7eSJed Brown 25119df49d7eSJed Brown /// Assemble the diagonal of a square linear Operator 25129df49d7eSJed Brown /// 25139df49d7eSJed Brown /// This sums into a Vector with the diagonal of a linear Operator. 25149df49d7eSJed Brown /// 25159df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 25169df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 25179df49d7eSJed Brown /// 25189df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 25199df49d7eSJed Brown /// * `assembled` - Vector to store assembled CeedOperator point block 25209df49d7eSJed Brown /// diagonal, provided in row-major form with an 25219df49d7eSJed Brown /// `ncomp * ncomp` block at each node. The dimensions of 25229df49d7eSJed Brown /// this vector are derived from the active vector for 25239df49d7eSJed Brown /// the CeedOperator. The array has shape 25249df49d7eSJed Brown /// `[nodes, component out, component in]`. 25259df49d7eSJed Brown pub fn linear_assemble_add_point_block_diagonal( 25269df49d7eSJed Brown &self, 25279df49d7eSJed Brown assembled: &mut Vector, 25289df49d7eSJed Brown ) -> crate::Result<i32> { 25299df49d7eSJed Brown self.op_core.linear_assemble_add_diagonal(assembled) 25309df49d7eSJed Brown } 25319df49d7eSJed Brown } 25329df49d7eSJed Brown 25339df49d7eSJed Brown // ----------------------------------------------------------------------------- 2534