1*9df49d7eSJed Brown // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2*9df49d7eSJed Brown // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3*9df49d7eSJed Brown // reserved. See files LICENSE and NOTICE for details. 4*9df49d7eSJed Brown // 5*9df49d7eSJed Brown // This file is part of CEED, a collection of benchmarks, miniapps, software 6*9df49d7eSJed Brown // libraries and APIs for efficient high-order finite element and spectral 7*9df49d7eSJed Brown // element discretizations for exascale applications. For more information and 8*9df49d7eSJed Brown // source code availability see http://github.com/ceed. 9*9df49d7eSJed Brown // 10*9df49d7eSJed Brown // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11*9df49d7eSJed Brown // a collaborative effort of two U.S. Department of Energy organizations (Office 12*9df49d7eSJed Brown // of Science and the National Nuclear Security Administration) responsible for 13*9df49d7eSJed Brown // the planning and preparation of a capable exascale ecosystem, including 14*9df49d7eSJed Brown // software, applications, hardware, advanced system engineering and early 15*9df49d7eSJed Brown // testbed platforms, in support of the nation's exascale computing imperative 16*9df49d7eSJed Brown 17*9df49d7eSJed Brown //! A Ceed Operator defines the finite/spectral element operator associated to a 18*9df49d7eSJed Brown //! Ceed QFunction. A Ceed Operator connects Ceed ElemRestrictions, 19*9df49d7eSJed Brown //! Ceed Bases, and Ceed QFunctions. 20*9df49d7eSJed Brown 21*9df49d7eSJed Brown use crate::prelude::*; 22*9df49d7eSJed Brown 23*9df49d7eSJed Brown // ----------------------------------------------------------------------------- 24*9df49d7eSJed Brown // CeedOperator context wrapper 25*9df49d7eSJed Brown // ----------------------------------------------------------------------------- 26*9df49d7eSJed Brown pub(crate) struct OperatorCore<'a> { 27*9df49d7eSJed Brown ceed: &'a crate::Ceed, 28*9df49d7eSJed Brown ptr: bind_ceed::CeedOperator, 29*9df49d7eSJed Brown } 30*9df49d7eSJed Brown 31*9df49d7eSJed Brown pub struct Operator<'a> { 32*9df49d7eSJed Brown op_core: OperatorCore<'a>, 33*9df49d7eSJed Brown } 34*9df49d7eSJed Brown 35*9df49d7eSJed Brown pub struct CompositeOperator<'a> { 36*9df49d7eSJed Brown op_core: OperatorCore<'a>, 37*9df49d7eSJed Brown } 38*9df49d7eSJed Brown 39*9df49d7eSJed Brown // ----------------------------------------------------------------------------- 40*9df49d7eSJed Brown // Destructor 41*9df49d7eSJed Brown // ----------------------------------------------------------------------------- 42*9df49d7eSJed Brown impl<'a> Drop for OperatorCore<'a> { 43*9df49d7eSJed Brown fn drop(&mut self) { 44*9df49d7eSJed Brown unsafe { 45*9df49d7eSJed Brown bind_ceed::CeedOperatorDestroy(&mut self.ptr); 46*9df49d7eSJed Brown } 47*9df49d7eSJed Brown } 48*9df49d7eSJed Brown } 49*9df49d7eSJed Brown 50*9df49d7eSJed Brown // ----------------------------------------------------------------------------- 51*9df49d7eSJed Brown // Display 52*9df49d7eSJed Brown // ----------------------------------------------------------------------------- 53*9df49d7eSJed Brown impl<'a> fmt::Display for OperatorCore<'a> { 54*9df49d7eSJed Brown fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 55*9df49d7eSJed Brown let mut ptr = std::ptr::null_mut(); 56*9df49d7eSJed Brown let mut sizeloc = crate::MAX_BUFFER_LENGTH; 57*9df49d7eSJed Brown let cstring = unsafe { 58*9df49d7eSJed Brown let file = bind_ceed::open_memstream(&mut ptr, &mut sizeloc); 59*9df49d7eSJed Brown bind_ceed::CeedOperatorView(self.ptr, file); 60*9df49d7eSJed Brown bind_ceed::fclose(file); 61*9df49d7eSJed Brown CString::from_raw(ptr) 62*9df49d7eSJed Brown }; 63*9df49d7eSJed Brown cstring.to_string_lossy().fmt(f) 64*9df49d7eSJed Brown } 65*9df49d7eSJed Brown } 66*9df49d7eSJed Brown 67*9df49d7eSJed Brown /// View an Operator 68*9df49d7eSJed Brown /// 69*9df49d7eSJed Brown /// ``` 70*9df49d7eSJed Brown /// # use libceed::prelude::*; 71*9df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 72*9df49d7eSJed Brown /// let qf = ceed.q_function_interior_by_name("Mass1DBuild").unwrap(); 73*9df49d7eSJed Brown /// 74*9df49d7eSJed Brown /// // Operator field arguments 75*9df49d7eSJed Brown /// let ne = 3; 76*9df49d7eSJed Brown /// let q = 4 as usize; 77*9df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 78*9df49d7eSJed Brown /// for i in 0..ne { 79*9df49d7eSJed Brown /// ind[2 * i + 0] = i as i32; 80*9df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32; 81*9df49d7eSJed Brown /// } 82*9df49d7eSJed Brown /// let r = ceed 83*9df49d7eSJed Brown /// .elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind) 84*9df49d7eSJed Brown /// .unwrap(); 85*9df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 86*9df49d7eSJed Brown /// let rq = ceed 87*9df49d7eSJed Brown /// .strided_elem_restriction(ne, 2, 1, q * ne, strides) 88*9df49d7eSJed Brown /// .unwrap(); 89*9df49d7eSJed Brown /// 90*9df49d7eSJed Brown /// let b = ceed 91*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss) 92*9df49d7eSJed Brown /// .unwrap(); 93*9df49d7eSJed Brown /// 94*9df49d7eSJed Brown /// // Operator fields 95*9df49d7eSJed Brown /// let op = ceed 96*9df49d7eSJed Brown /// .operator(&qf, QFunctionOpt::None, QFunctionOpt::None) 97*9df49d7eSJed Brown /// .unwrap() 98*9df49d7eSJed Brown /// .field("dx", &r, &b, VectorOpt::Active) 99*9df49d7eSJed Brown /// .unwrap() 100*9df49d7eSJed Brown /// .field("weights", ElemRestrictionOpt::None, &b, VectorOpt::None) 101*9df49d7eSJed Brown /// .unwrap() 102*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active) 103*9df49d7eSJed Brown /// .unwrap(); 104*9df49d7eSJed Brown /// 105*9df49d7eSJed Brown /// println!("{}", op); 106*9df49d7eSJed Brown /// ``` 107*9df49d7eSJed Brown impl<'a> fmt::Display for Operator<'a> { 108*9df49d7eSJed Brown fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 109*9df49d7eSJed Brown self.op_core.fmt(f) 110*9df49d7eSJed Brown } 111*9df49d7eSJed Brown } 112*9df49d7eSJed Brown 113*9df49d7eSJed Brown /// View a composite Operator 114*9df49d7eSJed Brown /// 115*9df49d7eSJed Brown /// ``` 116*9df49d7eSJed Brown /// # use libceed::prelude::*; 117*9df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 118*9df49d7eSJed Brown /// 119*9df49d7eSJed Brown /// // Sub operator field arguments 120*9df49d7eSJed Brown /// let ne = 3; 121*9df49d7eSJed Brown /// let q = 4 as usize; 122*9df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 123*9df49d7eSJed Brown /// for i in 0..ne { 124*9df49d7eSJed Brown /// ind[2 * i + 0] = i as i32; 125*9df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32; 126*9df49d7eSJed Brown /// } 127*9df49d7eSJed Brown /// let r = ceed 128*9df49d7eSJed Brown /// .elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind) 129*9df49d7eSJed Brown /// .unwrap(); 130*9df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 131*9df49d7eSJed Brown /// let rq = ceed 132*9df49d7eSJed Brown /// .strided_elem_restriction(ne, 2, 1, q * ne, strides) 133*9df49d7eSJed Brown /// .unwrap(); 134*9df49d7eSJed Brown /// 135*9df49d7eSJed Brown /// let b = ceed 136*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss) 137*9df49d7eSJed Brown /// .unwrap(); 138*9df49d7eSJed Brown /// 139*9df49d7eSJed Brown /// let qdata_mass = ceed.vector(q * ne).unwrap(); 140*9df49d7eSJed Brown /// let qdata_diff = ceed.vector(q * ne).unwrap(); 141*9df49d7eSJed Brown /// 142*9df49d7eSJed Brown /// let qf_mass = ceed.q_function_interior_by_name("MassApply").unwrap(); 143*9df49d7eSJed Brown /// let op_mass = ceed 144*9df49d7eSJed Brown /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None) 145*9df49d7eSJed Brown /// .unwrap() 146*9df49d7eSJed Brown /// .field("u", &r, &b, VectorOpt::Active) 147*9df49d7eSJed Brown /// .unwrap() 148*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, &qdata_mass) 149*9df49d7eSJed Brown /// .unwrap() 150*9df49d7eSJed Brown /// .field("v", &r, &b, VectorOpt::Active) 151*9df49d7eSJed Brown /// .unwrap(); 152*9df49d7eSJed Brown /// 153*9df49d7eSJed Brown /// let qf_diff = ceed.q_function_interior_by_name("Poisson1DApply").unwrap(); 154*9df49d7eSJed Brown /// let op_diff = ceed 155*9df49d7eSJed Brown /// .operator(&qf_diff, QFunctionOpt::None, QFunctionOpt::None) 156*9df49d7eSJed Brown /// .unwrap() 157*9df49d7eSJed Brown /// .field("du", &r, &b, VectorOpt::Active) 158*9df49d7eSJed Brown /// .unwrap() 159*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, &qdata_diff) 160*9df49d7eSJed Brown /// .unwrap() 161*9df49d7eSJed Brown /// .field("dv", &r, &b, VectorOpt::Active) 162*9df49d7eSJed Brown /// .unwrap(); 163*9df49d7eSJed Brown /// 164*9df49d7eSJed Brown /// let op = ceed 165*9df49d7eSJed Brown /// .composite_operator() 166*9df49d7eSJed Brown /// .unwrap() 167*9df49d7eSJed Brown /// .sub_operator(&op_mass) 168*9df49d7eSJed Brown /// .unwrap() 169*9df49d7eSJed Brown /// .sub_operator(&op_diff) 170*9df49d7eSJed Brown /// .unwrap(); 171*9df49d7eSJed Brown /// 172*9df49d7eSJed Brown /// println!("{}", op); 173*9df49d7eSJed Brown /// ``` 174*9df49d7eSJed Brown impl<'a> fmt::Display for CompositeOperator<'a> { 175*9df49d7eSJed Brown fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 176*9df49d7eSJed Brown self.op_core.fmt(f) 177*9df49d7eSJed Brown } 178*9df49d7eSJed Brown } 179*9df49d7eSJed Brown 180*9df49d7eSJed Brown // ----------------------------------------------------------------------------- 181*9df49d7eSJed Brown // Core functionality 182*9df49d7eSJed Brown // ----------------------------------------------------------------------------- 183*9df49d7eSJed Brown impl<'a> OperatorCore<'a> { 184*9df49d7eSJed Brown // Common implementations 185*9df49d7eSJed Brown pub fn apply(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> { 186*9df49d7eSJed Brown let ierr = unsafe { 187*9df49d7eSJed Brown bind_ceed::CeedOperatorApply( 188*9df49d7eSJed Brown self.ptr, 189*9df49d7eSJed Brown input.ptr, 190*9df49d7eSJed Brown output.ptr, 191*9df49d7eSJed Brown bind_ceed::CEED_REQUEST_IMMEDIATE, 192*9df49d7eSJed Brown ) 193*9df49d7eSJed Brown }; 194*9df49d7eSJed Brown self.ceed.check_error(ierr) 195*9df49d7eSJed Brown } 196*9df49d7eSJed Brown 197*9df49d7eSJed Brown pub fn apply_add(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> { 198*9df49d7eSJed Brown let ierr = unsafe { 199*9df49d7eSJed Brown bind_ceed::CeedOperatorApplyAdd( 200*9df49d7eSJed Brown self.ptr, 201*9df49d7eSJed Brown input.ptr, 202*9df49d7eSJed Brown output.ptr, 203*9df49d7eSJed Brown bind_ceed::CEED_REQUEST_IMMEDIATE, 204*9df49d7eSJed Brown ) 205*9df49d7eSJed Brown }; 206*9df49d7eSJed Brown self.ceed.check_error(ierr) 207*9df49d7eSJed Brown } 208*9df49d7eSJed Brown 209*9df49d7eSJed Brown pub fn linear_assemble_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> { 210*9df49d7eSJed Brown let ierr = unsafe { 211*9df49d7eSJed Brown bind_ceed::CeedOperatorLinearAssembleDiagonal( 212*9df49d7eSJed Brown self.ptr, 213*9df49d7eSJed Brown assembled.ptr, 214*9df49d7eSJed Brown bind_ceed::CEED_REQUEST_IMMEDIATE, 215*9df49d7eSJed Brown ) 216*9df49d7eSJed Brown }; 217*9df49d7eSJed Brown self.ceed.check_error(ierr) 218*9df49d7eSJed Brown } 219*9df49d7eSJed Brown 220*9df49d7eSJed Brown pub fn linear_assemble_add_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> { 221*9df49d7eSJed Brown let ierr = unsafe { 222*9df49d7eSJed Brown bind_ceed::CeedOperatorLinearAssembleAddDiagonal( 223*9df49d7eSJed Brown self.ptr, 224*9df49d7eSJed Brown assembled.ptr, 225*9df49d7eSJed Brown bind_ceed::CEED_REQUEST_IMMEDIATE, 226*9df49d7eSJed Brown ) 227*9df49d7eSJed Brown }; 228*9df49d7eSJed Brown self.ceed.check_error(ierr) 229*9df49d7eSJed Brown } 230*9df49d7eSJed Brown 231*9df49d7eSJed Brown pub fn linear_assemble_point_block_diagonal( 232*9df49d7eSJed Brown &self, 233*9df49d7eSJed Brown assembled: &mut Vector, 234*9df49d7eSJed Brown ) -> crate::Result<i32> { 235*9df49d7eSJed Brown let ierr = unsafe { 236*9df49d7eSJed Brown bind_ceed::CeedOperatorLinearAssemblePointBlockDiagonal( 237*9df49d7eSJed Brown self.ptr, 238*9df49d7eSJed Brown assembled.ptr, 239*9df49d7eSJed Brown bind_ceed::CEED_REQUEST_IMMEDIATE, 240*9df49d7eSJed Brown ) 241*9df49d7eSJed Brown }; 242*9df49d7eSJed Brown self.ceed.check_error(ierr) 243*9df49d7eSJed Brown } 244*9df49d7eSJed Brown 245*9df49d7eSJed Brown pub fn linear_assemble_add_point_block_diagonal( 246*9df49d7eSJed Brown &self, 247*9df49d7eSJed Brown assembled: &mut Vector, 248*9df49d7eSJed Brown ) -> crate::Result<i32> { 249*9df49d7eSJed Brown let ierr = unsafe { 250*9df49d7eSJed Brown bind_ceed::CeedOperatorLinearAssembleAddPointBlockDiagonal( 251*9df49d7eSJed Brown self.ptr, 252*9df49d7eSJed Brown assembled.ptr, 253*9df49d7eSJed Brown bind_ceed::CEED_REQUEST_IMMEDIATE, 254*9df49d7eSJed Brown ) 255*9df49d7eSJed Brown }; 256*9df49d7eSJed Brown self.ceed.check_error(ierr) 257*9df49d7eSJed Brown } 258*9df49d7eSJed Brown } 259*9df49d7eSJed Brown 260*9df49d7eSJed Brown // ----------------------------------------------------------------------------- 261*9df49d7eSJed Brown // Operator 262*9df49d7eSJed Brown // ----------------------------------------------------------------------------- 263*9df49d7eSJed Brown impl<'a> Operator<'a> { 264*9df49d7eSJed Brown // Constructor 265*9df49d7eSJed Brown pub fn create<'b>( 266*9df49d7eSJed Brown ceed: &'a crate::Ceed, 267*9df49d7eSJed Brown qf: impl Into<QFunctionOpt<'b>>, 268*9df49d7eSJed Brown dqf: impl Into<QFunctionOpt<'b>>, 269*9df49d7eSJed Brown dqfT: impl Into<QFunctionOpt<'b>>, 270*9df49d7eSJed Brown ) -> crate::Result<Self> { 271*9df49d7eSJed Brown let mut ptr = std::ptr::null_mut(); 272*9df49d7eSJed Brown let ierr = unsafe { 273*9df49d7eSJed Brown bind_ceed::CeedOperatorCreate( 274*9df49d7eSJed Brown ceed.ptr, 275*9df49d7eSJed Brown qf.into().to_raw(), 276*9df49d7eSJed Brown dqf.into().to_raw(), 277*9df49d7eSJed Brown dqfT.into().to_raw(), 278*9df49d7eSJed Brown &mut ptr, 279*9df49d7eSJed Brown ) 280*9df49d7eSJed Brown }; 281*9df49d7eSJed Brown ceed.check_error(ierr)?; 282*9df49d7eSJed Brown Ok(Self { 283*9df49d7eSJed Brown op_core: OperatorCore { ceed, ptr }, 284*9df49d7eSJed Brown }) 285*9df49d7eSJed Brown } 286*9df49d7eSJed Brown 287*9df49d7eSJed Brown fn from_raw(ceed: &'a crate::Ceed, ptr: bind_ceed::CeedOperator) -> crate::Result<Self> { 288*9df49d7eSJed Brown Ok(Self { 289*9df49d7eSJed Brown op_core: OperatorCore { ceed, ptr }, 290*9df49d7eSJed Brown }) 291*9df49d7eSJed Brown } 292*9df49d7eSJed Brown 293*9df49d7eSJed Brown /// Apply Operator to a vector 294*9df49d7eSJed Brown /// 295*9df49d7eSJed Brown /// * `input` - Input Vector 296*9df49d7eSJed Brown /// * `output` - Output Vector 297*9df49d7eSJed Brown /// 298*9df49d7eSJed Brown /// ``` 299*9df49d7eSJed Brown /// # use libceed::prelude::*; 300*9df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 301*9df49d7eSJed Brown /// let ne = 4; 302*9df49d7eSJed Brown /// let p = 3; 303*9df49d7eSJed Brown /// let q = 4; 304*9df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 305*9df49d7eSJed Brown /// 306*9df49d7eSJed Brown /// // Vectors 307*9df49d7eSJed Brown /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0]).unwrap(); 308*9df49d7eSJed Brown /// let mut qdata = ceed.vector(ne * q).unwrap(); 309*9df49d7eSJed Brown /// qdata.set_value(0.0); 310*9df49d7eSJed Brown /// let u = ceed.vector_from_slice(&vec![1.0; ndofs]).unwrap(); 311*9df49d7eSJed Brown /// let mut v = ceed.vector(ndofs).unwrap(); 312*9df49d7eSJed Brown /// v.set_value(0.0); 313*9df49d7eSJed Brown /// 314*9df49d7eSJed Brown /// // Restrictions 315*9df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 316*9df49d7eSJed Brown /// for i in 0..ne { 317*9df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 318*9df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 319*9df49d7eSJed Brown /// } 320*9df49d7eSJed Brown /// let rx = ceed 321*9df49d7eSJed Brown /// .elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx) 322*9df49d7eSJed Brown /// .unwrap(); 323*9df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 324*9df49d7eSJed Brown /// for i in 0..ne { 325*9df49d7eSJed Brown /// indu[p * i + 0] = i as i32; 326*9df49d7eSJed Brown /// indu[p * i + 1] = (i + 1) as i32; 327*9df49d7eSJed Brown /// indu[p * i + 2] = (i + 2) as i32; 328*9df49d7eSJed Brown /// } 329*9df49d7eSJed Brown /// let ru = ceed 330*9df49d7eSJed Brown /// .elem_restriction(ne, 3, 1, 1, ndofs, MemType::Host, &indu) 331*9df49d7eSJed Brown /// .unwrap(); 332*9df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 333*9df49d7eSJed Brown /// let rq = ceed 334*9df49d7eSJed Brown /// .strided_elem_restriction(ne, q, 1, q * ne, strides) 335*9df49d7eSJed Brown /// .unwrap(); 336*9df49d7eSJed Brown /// 337*9df49d7eSJed Brown /// // Bases 338*9df49d7eSJed Brown /// let bx = ceed 339*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss) 340*9df49d7eSJed Brown /// .unwrap(); 341*9df49d7eSJed Brown /// let bu = ceed 342*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, p, q, QuadMode::Gauss) 343*9df49d7eSJed Brown /// .unwrap(); 344*9df49d7eSJed Brown /// 345*9df49d7eSJed Brown /// // Build quadrature data 346*9df49d7eSJed Brown /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild").unwrap(); 347*9df49d7eSJed Brown /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None) 348*9df49d7eSJed Brown /// .unwrap() 349*9df49d7eSJed Brown /// .field("dx", &rx, &bx, VectorOpt::Active) 350*9df49d7eSJed Brown /// .unwrap() 351*9df49d7eSJed Brown /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None) 352*9df49d7eSJed Brown /// .unwrap() 353*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active) 354*9df49d7eSJed Brown /// .unwrap() 355*9df49d7eSJed Brown /// .apply(&x, &mut qdata) 356*9df49d7eSJed Brown /// .unwrap(); 357*9df49d7eSJed Brown /// 358*9df49d7eSJed Brown /// // Mass operator 359*9df49d7eSJed Brown /// let qf_mass = ceed.q_function_interior_by_name("MassApply").unwrap(); 360*9df49d7eSJed Brown /// let op_mass = ceed 361*9df49d7eSJed Brown /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None) 362*9df49d7eSJed Brown /// .unwrap() 363*9df49d7eSJed Brown /// .field("u", &ru, &bu, VectorOpt::Active) 364*9df49d7eSJed Brown /// .unwrap() 365*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, &qdata) 366*9df49d7eSJed Brown /// .unwrap() 367*9df49d7eSJed Brown /// .field("v", &ru, &bu, VectorOpt::Active) 368*9df49d7eSJed Brown /// .unwrap(); 369*9df49d7eSJed Brown /// 370*9df49d7eSJed Brown /// v.set_value(0.0); 371*9df49d7eSJed Brown /// op_mass.apply(&u, &mut v).unwrap(); 372*9df49d7eSJed Brown /// 373*9df49d7eSJed Brown /// // Check 374*9df49d7eSJed Brown /// let sum: f64 = v.view().iter().sum(); 375*9df49d7eSJed Brown /// assert!( 376*9df49d7eSJed Brown /// (sum - 2.0).abs() < 1e-15, 377*9df49d7eSJed Brown /// "Incorrect interval length computed" 378*9df49d7eSJed Brown /// ); 379*9df49d7eSJed Brown /// ``` 380*9df49d7eSJed Brown pub fn apply(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> { 381*9df49d7eSJed Brown self.op_core.apply(input, output) 382*9df49d7eSJed Brown } 383*9df49d7eSJed Brown 384*9df49d7eSJed Brown /// Apply Operator to a vector and add result to output vector 385*9df49d7eSJed Brown /// 386*9df49d7eSJed Brown /// * `input` - Input Vector 387*9df49d7eSJed Brown /// * `output` - Output Vector 388*9df49d7eSJed Brown /// 389*9df49d7eSJed Brown /// ``` 390*9df49d7eSJed Brown /// # use libceed::prelude::*; 391*9df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 392*9df49d7eSJed Brown /// let ne = 4; 393*9df49d7eSJed Brown /// let p = 3; 394*9df49d7eSJed Brown /// let q = 4; 395*9df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 396*9df49d7eSJed Brown /// 397*9df49d7eSJed Brown /// // Vectors 398*9df49d7eSJed Brown /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0]).unwrap(); 399*9df49d7eSJed Brown /// let mut qdata = ceed.vector(ne * q).unwrap(); 400*9df49d7eSJed Brown /// qdata.set_value(0.0); 401*9df49d7eSJed Brown /// let u = ceed.vector_from_slice(&vec![1.0; ndofs]).unwrap(); 402*9df49d7eSJed Brown /// let mut v = ceed.vector(ndofs).unwrap(); 403*9df49d7eSJed Brown /// 404*9df49d7eSJed Brown /// // Restrictions 405*9df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 406*9df49d7eSJed Brown /// for i in 0..ne { 407*9df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 408*9df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 409*9df49d7eSJed Brown /// } 410*9df49d7eSJed Brown /// let rx = ceed 411*9df49d7eSJed Brown /// .elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx) 412*9df49d7eSJed Brown /// .unwrap(); 413*9df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 414*9df49d7eSJed Brown /// for i in 0..ne { 415*9df49d7eSJed Brown /// indu[p * i + 0] = i as i32; 416*9df49d7eSJed Brown /// indu[p * i + 1] = (i + 1) as i32; 417*9df49d7eSJed Brown /// indu[p * i + 2] = (i + 2) as i32; 418*9df49d7eSJed Brown /// } 419*9df49d7eSJed Brown /// let ru = ceed 420*9df49d7eSJed Brown /// .elem_restriction(ne, 3, 1, 1, ndofs, MemType::Host, &indu) 421*9df49d7eSJed Brown /// .unwrap(); 422*9df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 423*9df49d7eSJed Brown /// let rq = ceed 424*9df49d7eSJed Brown /// .strided_elem_restriction(ne, q, 1, q * ne, strides) 425*9df49d7eSJed Brown /// .unwrap(); 426*9df49d7eSJed Brown /// 427*9df49d7eSJed Brown /// // Bases 428*9df49d7eSJed Brown /// let bx = ceed 429*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss) 430*9df49d7eSJed Brown /// .unwrap(); 431*9df49d7eSJed Brown /// let bu = ceed 432*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, p, q, QuadMode::Gauss) 433*9df49d7eSJed Brown /// .unwrap(); 434*9df49d7eSJed Brown /// 435*9df49d7eSJed Brown /// // Build quadrature data 436*9df49d7eSJed Brown /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild").unwrap(); 437*9df49d7eSJed Brown /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None) 438*9df49d7eSJed Brown /// .unwrap() 439*9df49d7eSJed Brown /// .field("dx", &rx, &bx, VectorOpt::Active) 440*9df49d7eSJed Brown /// .unwrap() 441*9df49d7eSJed Brown /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None) 442*9df49d7eSJed Brown /// .unwrap() 443*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active) 444*9df49d7eSJed Brown /// .unwrap() 445*9df49d7eSJed Brown /// .apply(&x, &mut qdata) 446*9df49d7eSJed Brown /// .unwrap(); 447*9df49d7eSJed Brown /// 448*9df49d7eSJed Brown /// // Mass operator 449*9df49d7eSJed Brown /// let qf_mass = ceed.q_function_interior_by_name("MassApply").unwrap(); 450*9df49d7eSJed Brown /// let op_mass = ceed 451*9df49d7eSJed Brown /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None) 452*9df49d7eSJed Brown /// .unwrap() 453*9df49d7eSJed Brown /// .field("u", &ru, &bu, VectorOpt::Active) 454*9df49d7eSJed Brown /// .unwrap() 455*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, &qdata) 456*9df49d7eSJed Brown /// .unwrap() 457*9df49d7eSJed Brown /// .field("v", &ru, &bu, VectorOpt::Active) 458*9df49d7eSJed Brown /// .unwrap(); 459*9df49d7eSJed Brown /// 460*9df49d7eSJed Brown /// v.set_value(1.0); 461*9df49d7eSJed Brown /// op_mass.apply_add(&u, &mut v).unwrap(); 462*9df49d7eSJed Brown /// 463*9df49d7eSJed Brown /// // Check 464*9df49d7eSJed Brown /// let sum: f64 = v.view().iter().sum(); 465*9df49d7eSJed Brown /// assert!( 466*9df49d7eSJed Brown /// (sum - (2.0 + ndofs as f64)).abs() < 1e-15, 467*9df49d7eSJed Brown /// "Incorrect interval length computed and added" 468*9df49d7eSJed Brown /// ); 469*9df49d7eSJed Brown /// ``` 470*9df49d7eSJed Brown pub fn apply_add(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> { 471*9df49d7eSJed Brown self.op_core.apply_add(input, output) 472*9df49d7eSJed Brown } 473*9df49d7eSJed Brown 474*9df49d7eSJed Brown /// Provide a field to a Operator for use by its QFunction 475*9df49d7eSJed Brown /// 476*9df49d7eSJed Brown /// * `fieldname` - Name of the field (to be matched with the name used by 477*9df49d7eSJed Brown /// the QFunction) 478*9df49d7eSJed Brown /// * `r` - ElemRestriction 479*9df49d7eSJed Brown /// * `b` - Basis in which the field resides or `BasisCollocated` if 480*9df49d7eSJed Brown /// collocated with quadrature points 481*9df49d7eSJed Brown /// * `v` - Vector to be used by Operator or `VectorActive` if field 482*9df49d7eSJed Brown /// is active or `VectorNone` if using `Weight` with the 483*9df49d7eSJed Brown /// QFunction 484*9df49d7eSJed Brown /// 485*9df49d7eSJed Brown /// 486*9df49d7eSJed Brown /// ``` 487*9df49d7eSJed Brown /// # use libceed::prelude::*; 488*9df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 489*9df49d7eSJed Brown /// let qf = ceed.q_function_interior_by_name("Mass1DBuild").unwrap(); 490*9df49d7eSJed Brown /// let mut op = ceed 491*9df49d7eSJed Brown /// .operator(&qf, QFunctionOpt::None, QFunctionOpt::None) 492*9df49d7eSJed Brown /// .unwrap(); 493*9df49d7eSJed Brown /// 494*9df49d7eSJed Brown /// // Operator field arguments 495*9df49d7eSJed Brown /// let ne = 3; 496*9df49d7eSJed Brown /// let q = 4; 497*9df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * ne]; 498*9df49d7eSJed Brown /// for i in 0..ne { 499*9df49d7eSJed Brown /// ind[2 * i + 0] = i as i32; 500*9df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32; 501*9df49d7eSJed Brown /// } 502*9df49d7eSJed Brown /// let r = ceed 503*9df49d7eSJed Brown /// .elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &ind) 504*9df49d7eSJed Brown /// .unwrap(); 505*9df49d7eSJed Brown /// 506*9df49d7eSJed Brown /// let b = ceed 507*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss) 508*9df49d7eSJed Brown /// .unwrap(); 509*9df49d7eSJed Brown /// 510*9df49d7eSJed Brown /// // Operator field 511*9df49d7eSJed Brown /// op = op.field("dx", &r, &b, VectorOpt::Active).unwrap(); 512*9df49d7eSJed Brown /// ``` 513*9df49d7eSJed Brown #[allow(unused_mut)] 514*9df49d7eSJed Brown pub fn field<'b>( 515*9df49d7eSJed Brown mut self, 516*9df49d7eSJed Brown fieldname: &str, 517*9df49d7eSJed Brown r: impl Into<ElemRestrictionOpt<'b>>, 518*9df49d7eSJed Brown b: impl Into<BasisOpt<'b>>, 519*9df49d7eSJed Brown v: impl Into<VectorOpt<'b>>, 520*9df49d7eSJed Brown ) -> crate::Result<Self> { 521*9df49d7eSJed Brown let fieldname = CString::new(fieldname).expect("CString::new failed"); 522*9df49d7eSJed Brown let fieldname = fieldname.as_ptr() as *const i8; 523*9df49d7eSJed Brown let ierr = unsafe { 524*9df49d7eSJed Brown bind_ceed::CeedOperatorSetField( 525*9df49d7eSJed Brown self.op_core.ptr, 526*9df49d7eSJed Brown fieldname, 527*9df49d7eSJed Brown r.into().to_raw(), 528*9df49d7eSJed Brown b.into().to_raw(), 529*9df49d7eSJed Brown v.into().to_raw(), 530*9df49d7eSJed Brown ) 531*9df49d7eSJed Brown }; 532*9df49d7eSJed Brown self.op_core.ceed.check_error(ierr)?; 533*9df49d7eSJed Brown Ok(self) 534*9df49d7eSJed Brown } 535*9df49d7eSJed Brown 536*9df49d7eSJed Brown /// Assemble the diagonal of a square linear Operator 537*9df49d7eSJed Brown /// 538*9df49d7eSJed Brown /// This overwrites a Vector with the diagonal of a linear Operator. 539*9df49d7eSJed Brown /// 540*9df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 541*9df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 542*9df49d7eSJed Brown /// 543*9df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 544*9df49d7eSJed Brown /// * `assembled` - Vector to store assembled Operator diagonal 545*9df49d7eSJed Brown /// 546*9df49d7eSJed Brown /// ``` 547*9df49d7eSJed Brown /// # use libceed::prelude::*; 548*9df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 549*9df49d7eSJed Brown /// let ne = 4; 550*9df49d7eSJed Brown /// let p = 3; 551*9df49d7eSJed Brown /// let q = 4; 552*9df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 553*9df49d7eSJed Brown /// 554*9df49d7eSJed Brown /// // Vectors 555*9df49d7eSJed Brown /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0]).unwrap(); 556*9df49d7eSJed Brown /// let mut qdata = ceed.vector(ne * q).unwrap(); 557*9df49d7eSJed Brown /// qdata.set_value(0.0); 558*9df49d7eSJed Brown /// let mut u = ceed.vector(ndofs).unwrap(); 559*9df49d7eSJed Brown /// u.set_value(1.0); 560*9df49d7eSJed Brown /// let mut v = ceed.vector(ndofs).unwrap(); 561*9df49d7eSJed Brown /// v.set_value(0.0); 562*9df49d7eSJed Brown /// 563*9df49d7eSJed Brown /// // Restrictions 564*9df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 565*9df49d7eSJed Brown /// for i in 0..ne { 566*9df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 567*9df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 568*9df49d7eSJed Brown /// } 569*9df49d7eSJed Brown /// let rx = ceed 570*9df49d7eSJed Brown /// .elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx) 571*9df49d7eSJed Brown /// .unwrap(); 572*9df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 573*9df49d7eSJed Brown /// for i in 0..ne { 574*9df49d7eSJed Brown /// indu[p * i + 0] = (2 * i) as i32; 575*9df49d7eSJed Brown /// indu[p * i + 1] = (2 * i + 1) as i32; 576*9df49d7eSJed Brown /// indu[p * i + 2] = (2 * i + 2) as i32; 577*9df49d7eSJed Brown /// } 578*9df49d7eSJed Brown /// let ru = ceed 579*9df49d7eSJed Brown /// .elem_restriction(ne, p, 1, 1, ndofs, MemType::Host, &indu) 580*9df49d7eSJed Brown /// .unwrap(); 581*9df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 582*9df49d7eSJed Brown /// let rq = ceed 583*9df49d7eSJed Brown /// .strided_elem_restriction(ne, q, 1, q * ne, strides) 584*9df49d7eSJed Brown /// .unwrap(); 585*9df49d7eSJed Brown /// 586*9df49d7eSJed Brown /// // Bases 587*9df49d7eSJed Brown /// let bx = ceed 588*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss) 589*9df49d7eSJed Brown /// .unwrap(); 590*9df49d7eSJed Brown /// let bu = ceed 591*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, p, q, QuadMode::Gauss) 592*9df49d7eSJed Brown /// .unwrap(); 593*9df49d7eSJed Brown /// 594*9df49d7eSJed Brown /// // Build quadrature data 595*9df49d7eSJed Brown /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild").unwrap(); 596*9df49d7eSJed Brown /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None) 597*9df49d7eSJed Brown /// .unwrap() 598*9df49d7eSJed Brown /// .field("dx", &rx, &bx, VectorOpt::Active) 599*9df49d7eSJed Brown /// .unwrap() 600*9df49d7eSJed Brown /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None) 601*9df49d7eSJed Brown /// .unwrap() 602*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active) 603*9df49d7eSJed Brown /// .unwrap() 604*9df49d7eSJed Brown /// .apply(&x, &mut qdata) 605*9df49d7eSJed Brown /// .unwrap(); 606*9df49d7eSJed Brown /// 607*9df49d7eSJed Brown /// // Mass operator 608*9df49d7eSJed Brown /// let qf_mass = ceed.q_function_interior_by_name("MassApply").unwrap(); 609*9df49d7eSJed Brown /// let op_mass = ceed 610*9df49d7eSJed Brown /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None) 611*9df49d7eSJed Brown /// .unwrap() 612*9df49d7eSJed Brown /// .field("u", &ru, &bu, VectorOpt::Active) 613*9df49d7eSJed Brown /// .unwrap() 614*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, &qdata) 615*9df49d7eSJed Brown /// .unwrap() 616*9df49d7eSJed Brown /// .field("v", &ru, &bu, VectorOpt::Active) 617*9df49d7eSJed Brown /// .unwrap(); 618*9df49d7eSJed Brown /// 619*9df49d7eSJed Brown /// // Diagonal 620*9df49d7eSJed Brown /// let mut diag = ceed.vector(ndofs).unwrap(); 621*9df49d7eSJed Brown /// diag.set_value(0.0); 622*9df49d7eSJed Brown /// op_mass.linear_assemble_diagonal(&mut diag).unwrap(); 623*9df49d7eSJed Brown /// 624*9df49d7eSJed Brown /// // Manual diagonal computation 625*9df49d7eSJed Brown /// let mut true_diag = ceed.vector(ndofs).unwrap(); 626*9df49d7eSJed Brown /// for i in 0..ndofs { 627*9df49d7eSJed Brown /// u.set_value(0.0); 628*9df49d7eSJed Brown /// { 629*9df49d7eSJed Brown /// let mut u_array = u.view_mut(); 630*9df49d7eSJed Brown /// u_array[i] = 1.; 631*9df49d7eSJed Brown /// } 632*9df49d7eSJed Brown /// 633*9df49d7eSJed Brown /// op_mass.apply(&u, &mut v).unwrap(); 634*9df49d7eSJed Brown /// 635*9df49d7eSJed Brown /// { 636*9df49d7eSJed Brown /// let v_array = v.view_mut(); 637*9df49d7eSJed Brown /// let mut true_array = true_diag.view_mut(); 638*9df49d7eSJed Brown /// true_array[i] = v_array[i]; 639*9df49d7eSJed Brown /// } 640*9df49d7eSJed Brown /// } 641*9df49d7eSJed Brown /// 642*9df49d7eSJed Brown /// // Check 643*9df49d7eSJed Brown /// diag.view() 644*9df49d7eSJed Brown /// .iter() 645*9df49d7eSJed Brown /// .zip(true_diag.view().iter()) 646*9df49d7eSJed Brown /// .for_each(|(computed, actual)| { 647*9df49d7eSJed Brown /// assert!( 648*9df49d7eSJed Brown /// (*computed - *actual).abs() < 1e-15, 649*9df49d7eSJed Brown /// "Diagonal entry incorrect" 650*9df49d7eSJed Brown /// ); 651*9df49d7eSJed Brown /// }); 652*9df49d7eSJed Brown /// ``` 653*9df49d7eSJed Brown pub fn linear_assemble_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> { 654*9df49d7eSJed Brown self.op_core.linear_assemble_diagonal(assembled) 655*9df49d7eSJed Brown } 656*9df49d7eSJed Brown 657*9df49d7eSJed Brown /// Assemble the diagonal of a square linear Operator 658*9df49d7eSJed Brown /// 659*9df49d7eSJed Brown /// This sums into a Vector with the diagonal of a linear Operator. 660*9df49d7eSJed Brown /// 661*9df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 662*9df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 663*9df49d7eSJed Brown /// 664*9df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 665*9df49d7eSJed Brown /// * `assembled` - Vector to store assembled Operator diagonal 666*9df49d7eSJed Brown /// 667*9df49d7eSJed Brown /// 668*9df49d7eSJed Brown /// ``` 669*9df49d7eSJed Brown /// # use libceed::prelude::*; 670*9df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 671*9df49d7eSJed Brown /// let ne = 4; 672*9df49d7eSJed Brown /// let p = 3; 673*9df49d7eSJed Brown /// let q = 4; 674*9df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 675*9df49d7eSJed Brown /// 676*9df49d7eSJed Brown /// // Vectors 677*9df49d7eSJed Brown /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0]).unwrap(); 678*9df49d7eSJed Brown /// let mut qdata = ceed.vector(ne * q).unwrap(); 679*9df49d7eSJed Brown /// qdata.set_value(0.0); 680*9df49d7eSJed Brown /// let mut u = ceed.vector(ndofs).unwrap(); 681*9df49d7eSJed Brown /// u.set_value(1.0); 682*9df49d7eSJed Brown /// let mut v = ceed.vector(ndofs).unwrap(); 683*9df49d7eSJed Brown /// v.set_value(0.0); 684*9df49d7eSJed Brown /// 685*9df49d7eSJed Brown /// // Restrictions 686*9df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 687*9df49d7eSJed Brown /// for i in 0..ne { 688*9df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 689*9df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 690*9df49d7eSJed Brown /// } 691*9df49d7eSJed Brown /// let rx = ceed 692*9df49d7eSJed Brown /// .elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx) 693*9df49d7eSJed Brown /// .unwrap(); 694*9df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 695*9df49d7eSJed Brown /// for i in 0..ne { 696*9df49d7eSJed Brown /// indu[p * i + 0] = (2 * i) as i32; 697*9df49d7eSJed Brown /// indu[p * i + 1] = (2 * i + 1) as i32; 698*9df49d7eSJed Brown /// indu[p * i + 2] = (2 * i + 2) as i32; 699*9df49d7eSJed Brown /// } 700*9df49d7eSJed Brown /// let ru = ceed 701*9df49d7eSJed Brown /// .elem_restriction(ne, p, 1, 1, ndofs, MemType::Host, &indu) 702*9df49d7eSJed Brown /// .unwrap(); 703*9df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 704*9df49d7eSJed Brown /// let rq = ceed 705*9df49d7eSJed Brown /// .strided_elem_restriction(ne, q, 1, q * ne, strides) 706*9df49d7eSJed Brown /// .unwrap(); 707*9df49d7eSJed Brown /// 708*9df49d7eSJed Brown /// // Bases 709*9df49d7eSJed Brown /// let bx = ceed 710*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss) 711*9df49d7eSJed Brown /// .unwrap(); 712*9df49d7eSJed Brown /// let bu = ceed 713*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, p, q, QuadMode::Gauss) 714*9df49d7eSJed Brown /// .unwrap(); 715*9df49d7eSJed Brown /// 716*9df49d7eSJed Brown /// // Build quadrature data 717*9df49d7eSJed Brown /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild").unwrap(); 718*9df49d7eSJed Brown /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None) 719*9df49d7eSJed Brown /// .unwrap() 720*9df49d7eSJed Brown /// .field("dx", &rx, &bx, VectorOpt::Active) 721*9df49d7eSJed Brown /// .unwrap() 722*9df49d7eSJed Brown /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None) 723*9df49d7eSJed Brown /// .unwrap() 724*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active) 725*9df49d7eSJed Brown /// .unwrap() 726*9df49d7eSJed Brown /// .apply(&x, &mut qdata) 727*9df49d7eSJed Brown /// .unwrap(); 728*9df49d7eSJed Brown /// 729*9df49d7eSJed Brown /// // Mass operator 730*9df49d7eSJed Brown /// let qf_mass = ceed.q_function_interior_by_name("MassApply").unwrap(); 731*9df49d7eSJed Brown /// let op_mass = ceed 732*9df49d7eSJed Brown /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None) 733*9df49d7eSJed Brown /// .unwrap() 734*9df49d7eSJed Brown /// .field("u", &ru, &bu, VectorOpt::Active) 735*9df49d7eSJed Brown /// .unwrap() 736*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, &qdata) 737*9df49d7eSJed Brown /// .unwrap() 738*9df49d7eSJed Brown /// .field("v", &ru, &bu, VectorOpt::Active) 739*9df49d7eSJed Brown /// .unwrap(); 740*9df49d7eSJed Brown /// 741*9df49d7eSJed Brown /// // Diagonal 742*9df49d7eSJed Brown /// let mut diag = ceed.vector(ndofs).unwrap(); 743*9df49d7eSJed Brown /// diag.set_value(1.0); 744*9df49d7eSJed Brown /// op_mass.linear_assemble_add_diagonal(&mut diag).unwrap(); 745*9df49d7eSJed Brown /// 746*9df49d7eSJed Brown /// // Manual diagonal computation 747*9df49d7eSJed Brown /// let mut true_diag = ceed.vector(ndofs).unwrap(); 748*9df49d7eSJed Brown /// for i in 0..ndofs { 749*9df49d7eSJed Brown /// u.set_value(0.0); 750*9df49d7eSJed Brown /// { 751*9df49d7eSJed Brown /// let mut u_array = u.view_mut(); 752*9df49d7eSJed Brown /// u_array[i] = 1.; 753*9df49d7eSJed Brown /// } 754*9df49d7eSJed Brown /// 755*9df49d7eSJed Brown /// op_mass.apply(&u, &mut v).unwrap(); 756*9df49d7eSJed Brown /// 757*9df49d7eSJed Brown /// { 758*9df49d7eSJed Brown /// let v_array = v.view_mut(); 759*9df49d7eSJed Brown /// let mut true_array = true_diag.view_mut(); 760*9df49d7eSJed Brown /// true_array[i] = v_array[i] + 1.0; 761*9df49d7eSJed Brown /// } 762*9df49d7eSJed Brown /// } 763*9df49d7eSJed Brown /// 764*9df49d7eSJed Brown /// // Check 765*9df49d7eSJed Brown /// diag.view() 766*9df49d7eSJed Brown /// .iter() 767*9df49d7eSJed Brown /// .zip(true_diag.view().iter()) 768*9df49d7eSJed Brown /// .for_each(|(computed, actual)| { 769*9df49d7eSJed Brown /// assert!( 770*9df49d7eSJed Brown /// (*computed - *actual).abs() < 1e-15, 771*9df49d7eSJed Brown /// "Diagonal entry incorrect" 772*9df49d7eSJed Brown /// ); 773*9df49d7eSJed Brown /// }); 774*9df49d7eSJed Brown /// ``` 775*9df49d7eSJed Brown pub fn linear_assemble_add_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> { 776*9df49d7eSJed Brown self.op_core.linear_assemble_add_diagonal(assembled) 777*9df49d7eSJed Brown } 778*9df49d7eSJed Brown 779*9df49d7eSJed Brown /// Assemble the point block diagonal of a square linear Operator 780*9df49d7eSJed Brown /// 781*9df49d7eSJed Brown /// This overwrites a Vector with the point block diagonal of a linear 782*9df49d7eSJed Brown /// Operator. 783*9df49d7eSJed Brown /// 784*9df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 785*9df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 786*9df49d7eSJed Brown /// 787*9df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 788*9df49d7eSJed Brown /// * `assembled` - Vector to store assembled CeedOperator point block 789*9df49d7eSJed Brown /// diagonal, provided in row-major form with an 790*9df49d7eSJed Brown /// `ncomp * ncomp` block at each node. The dimensions of 791*9df49d7eSJed Brown /// this vector are derived from the active vector for 792*9df49d7eSJed Brown /// the CeedOperator. The array has shape 793*9df49d7eSJed Brown /// `[nodes, component out, component in]`. 794*9df49d7eSJed Brown /// 795*9df49d7eSJed Brown /// ``` 796*9df49d7eSJed Brown /// # use libceed::prelude::*; 797*9df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 798*9df49d7eSJed Brown /// let ne = 4; 799*9df49d7eSJed Brown /// let p = 3; 800*9df49d7eSJed Brown /// let q = 4; 801*9df49d7eSJed Brown /// let ncomp = 2; 802*9df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 803*9df49d7eSJed Brown /// 804*9df49d7eSJed Brown /// // Vectors 805*9df49d7eSJed Brown /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0]).unwrap(); 806*9df49d7eSJed Brown /// let mut qdata = ceed.vector(ne * q).unwrap(); 807*9df49d7eSJed Brown /// qdata.set_value(0.0); 808*9df49d7eSJed Brown /// let mut u = ceed.vector(ncomp * ndofs).unwrap(); 809*9df49d7eSJed Brown /// u.set_value(1.0); 810*9df49d7eSJed Brown /// let mut v = ceed.vector(ncomp * ndofs).unwrap(); 811*9df49d7eSJed Brown /// v.set_value(0.0); 812*9df49d7eSJed Brown /// 813*9df49d7eSJed Brown /// // Restrictions 814*9df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 815*9df49d7eSJed Brown /// for i in 0..ne { 816*9df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 817*9df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 818*9df49d7eSJed Brown /// } 819*9df49d7eSJed Brown /// let rx = ceed 820*9df49d7eSJed Brown /// .elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx) 821*9df49d7eSJed Brown /// .unwrap(); 822*9df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 823*9df49d7eSJed Brown /// for i in 0..ne { 824*9df49d7eSJed Brown /// indu[p * i + 0] = (2 * i) as i32; 825*9df49d7eSJed Brown /// indu[p * i + 1] = (2 * i + 1) as i32; 826*9df49d7eSJed Brown /// indu[p * i + 2] = (2 * i + 2) as i32; 827*9df49d7eSJed Brown /// } 828*9df49d7eSJed Brown /// let ru = ceed 829*9df49d7eSJed Brown /// .elem_restriction(ne, p, ncomp, ndofs, ncomp * ndofs, MemType::Host, &indu) 830*9df49d7eSJed Brown /// .unwrap(); 831*9df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 832*9df49d7eSJed Brown /// let rq = ceed 833*9df49d7eSJed Brown /// .strided_elem_restriction(ne, q, 1, q * ne, strides) 834*9df49d7eSJed Brown /// .unwrap(); 835*9df49d7eSJed Brown /// 836*9df49d7eSJed Brown /// // Bases 837*9df49d7eSJed Brown /// let bx = ceed 838*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss) 839*9df49d7eSJed Brown /// .unwrap(); 840*9df49d7eSJed Brown /// let bu = ceed 841*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, ncomp, p, q, QuadMode::Gauss) 842*9df49d7eSJed Brown /// .unwrap(); 843*9df49d7eSJed Brown /// 844*9df49d7eSJed Brown /// // Build quadrature data 845*9df49d7eSJed Brown /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild").unwrap(); 846*9df49d7eSJed Brown /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None) 847*9df49d7eSJed Brown /// .unwrap() 848*9df49d7eSJed Brown /// .field("dx", &rx, &bx, VectorOpt::Active) 849*9df49d7eSJed Brown /// .unwrap() 850*9df49d7eSJed Brown /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None) 851*9df49d7eSJed Brown /// .unwrap() 852*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active) 853*9df49d7eSJed Brown /// .unwrap() 854*9df49d7eSJed Brown /// .apply(&x, &mut qdata) 855*9df49d7eSJed Brown /// .unwrap(); 856*9df49d7eSJed Brown /// 857*9df49d7eSJed Brown /// // Mass operator 858*9df49d7eSJed Brown /// let mut mass_2_comp = |[u, qdata, ..]: QFunctionInputs, [v, ..]: QFunctionOutputs| { 859*9df49d7eSJed Brown /// // Number of quadrature points 860*9df49d7eSJed Brown /// let q = qdata.len(); 861*9df49d7eSJed Brown /// 862*9df49d7eSJed Brown /// // Iterate over quadrature points 863*9df49d7eSJed Brown /// for i in 0..q { 864*9df49d7eSJed Brown /// v[i + 0 * q] = u[i + 1 * q] * qdata[i]; 865*9df49d7eSJed Brown /// v[i + 1 * q] = u[i + 0 * q] * qdata[i]; 866*9df49d7eSJed Brown /// } 867*9df49d7eSJed Brown /// 868*9df49d7eSJed Brown /// // Return clean error code 869*9df49d7eSJed Brown /// 0 870*9df49d7eSJed Brown /// }; 871*9df49d7eSJed Brown /// 872*9df49d7eSJed Brown /// let qf_mass = ceed 873*9df49d7eSJed Brown /// .q_function_interior(1, Box::new(mass_2_comp)) 874*9df49d7eSJed Brown /// .unwrap() 875*9df49d7eSJed Brown /// .input("u", 2, EvalMode::Interp) 876*9df49d7eSJed Brown /// .unwrap() 877*9df49d7eSJed Brown /// .input("qdata", 1, EvalMode::None) 878*9df49d7eSJed Brown /// .unwrap() 879*9df49d7eSJed Brown /// .output("v", 2, EvalMode::Interp) 880*9df49d7eSJed Brown /// .unwrap(); 881*9df49d7eSJed Brown /// 882*9df49d7eSJed Brown /// let op_mass = ceed 883*9df49d7eSJed Brown /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None) 884*9df49d7eSJed Brown /// .unwrap() 885*9df49d7eSJed Brown /// .field("u", &ru, &bu, VectorOpt::Active) 886*9df49d7eSJed Brown /// .unwrap() 887*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, &qdata) 888*9df49d7eSJed Brown /// .unwrap() 889*9df49d7eSJed Brown /// .field("v", &ru, &bu, VectorOpt::Active) 890*9df49d7eSJed Brown /// .unwrap(); 891*9df49d7eSJed Brown /// 892*9df49d7eSJed Brown /// // Diagonal 893*9df49d7eSJed Brown /// let mut diag = ceed.vector(ncomp * ncomp * ndofs).unwrap(); 894*9df49d7eSJed Brown /// diag.set_value(0.0); 895*9df49d7eSJed Brown /// op_mass 896*9df49d7eSJed Brown /// .linear_assemble_point_block_diagonal(&mut diag) 897*9df49d7eSJed Brown /// .unwrap(); 898*9df49d7eSJed Brown /// 899*9df49d7eSJed Brown /// // Manual diagonal computation 900*9df49d7eSJed Brown /// let mut true_diag = ceed.vector(ncomp * ncomp * ndofs).unwrap(); 901*9df49d7eSJed Brown /// for i in 0..ndofs { 902*9df49d7eSJed Brown /// for j in 0..ncomp { 903*9df49d7eSJed Brown /// u.set_value(0.0); 904*9df49d7eSJed Brown /// { 905*9df49d7eSJed Brown /// let mut u_array = u.view_mut(); 906*9df49d7eSJed Brown /// u_array[i + j * ndofs] = 1.; 907*9df49d7eSJed Brown /// } 908*9df49d7eSJed Brown /// 909*9df49d7eSJed Brown /// op_mass.apply(&u, &mut v).unwrap(); 910*9df49d7eSJed Brown /// 911*9df49d7eSJed Brown /// { 912*9df49d7eSJed Brown /// let v_array = v.view_mut(); 913*9df49d7eSJed Brown /// let mut true_array = true_diag.view_mut(); 914*9df49d7eSJed Brown /// for k in 0..ncomp { 915*9df49d7eSJed Brown /// true_array[i * ncomp * ncomp + k * ncomp + j] = v_array[i + k * ndofs]; 916*9df49d7eSJed Brown /// } 917*9df49d7eSJed Brown /// } 918*9df49d7eSJed Brown /// } 919*9df49d7eSJed Brown /// } 920*9df49d7eSJed Brown /// 921*9df49d7eSJed Brown /// // Check 922*9df49d7eSJed Brown /// diag.view() 923*9df49d7eSJed Brown /// .iter() 924*9df49d7eSJed Brown /// .zip(true_diag.view().iter()) 925*9df49d7eSJed Brown /// .for_each(|(computed, actual)| { 926*9df49d7eSJed Brown /// assert!( 927*9df49d7eSJed Brown /// (*computed - *actual).abs() < 1e-15, 928*9df49d7eSJed Brown /// "Diagonal entry incorrect" 929*9df49d7eSJed Brown /// ); 930*9df49d7eSJed Brown /// }); 931*9df49d7eSJed Brown /// ``` 932*9df49d7eSJed Brown pub fn linear_assemble_point_block_diagonal( 933*9df49d7eSJed Brown &self, 934*9df49d7eSJed Brown assembled: &mut Vector, 935*9df49d7eSJed Brown ) -> crate::Result<i32> { 936*9df49d7eSJed Brown self.op_core.linear_assemble_point_block_diagonal(assembled) 937*9df49d7eSJed Brown } 938*9df49d7eSJed Brown 939*9df49d7eSJed Brown /// Assemble the point block diagonal of a square linear Operator 940*9df49d7eSJed Brown /// 941*9df49d7eSJed Brown /// This sums into a Vector with the point block diagonal of a linear 942*9df49d7eSJed Brown /// Operator. 943*9df49d7eSJed Brown /// 944*9df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 945*9df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 946*9df49d7eSJed Brown /// 947*9df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 948*9df49d7eSJed Brown /// * `assembled` - Vector to store assembled CeedOperator point block 949*9df49d7eSJed Brown /// diagonal, provided in row-major form with an 950*9df49d7eSJed Brown /// `ncomp * ncomp` block at each node. The dimensions of 951*9df49d7eSJed Brown /// this vector are derived from the active vector for 952*9df49d7eSJed Brown /// the CeedOperator. The array has shape 953*9df49d7eSJed Brown /// `[nodes, component out, component in]`. 954*9df49d7eSJed Brown /// 955*9df49d7eSJed Brown /// ``` 956*9df49d7eSJed Brown /// # use libceed::prelude::*; 957*9df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 958*9df49d7eSJed Brown /// let ne = 4; 959*9df49d7eSJed Brown /// let p = 3; 960*9df49d7eSJed Brown /// let q = 4; 961*9df49d7eSJed Brown /// let ncomp = 2; 962*9df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 963*9df49d7eSJed Brown /// 964*9df49d7eSJed Brown /// // Vectors 965*9df49d7eSJed Brown /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0]).unwrap(); 966*9df49d7eSJed Brown /// let mut qdata = ceed.vector(ne * q).unwrap(); 967*9df49d7eSJed Brown /// qdata.set_value(0.0); 968*9df49d7eSJed Brown /// let mut u = ceed.vector(ncomp * ndofs).unwrap(); 969*9df49d7eSJed Brown /// u.set_value(1.0); 970*9df49d7eSJed Brown /// let mut v = ceed.vector(ncomp * ndofs).unwrap(); 971*9df49d7eSJed Brown /// v.set_value(0.0); 972*9df49d7eSJed Brown /// 973*9df49d7eSJed Brown /// // Restrictions 974*9df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 975*9df49d7eSJed Brown /// for i in 0..ne { 976*9df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 977*9df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 978*9df49d7eSJed Brown /// } 979*9df49d7eSJed Brown /// let rx = ceed 980*9df49d7eSJed Brown /// .elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx) 981*9df49d7eSJed Brown /// .unwrap(); 982*9df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 983*9df49d7eSJed Brown /// for i in 0..ne { 984*9df49d7eSJed Brown /// indu[p * i + 0] = (2 * i) as i32; 985*9df49d7eSJed Brown /// indu[p * i + 1] = (2 * i + 1) as i32; 986*9df49d7eSJed Brown /// indu[p * i + 2] = (2 * i + 2) as i32; 987*9df49d7eSJed Brown /// } 988*9df49d7eSJed Brown /// let ru = ceed 989*9df49d7eSJed Brown /// .elem_restriction(ne, p, ncomp, ndofs, ncomp * ndofs, MemType::Host, &indu) 990*9df49d7eSJed Brown /// .unwrap(); 991*9df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 992*9df49d7eSJed Brown /// let rq = ceed 993*9df49d7eSJed Brown /// .strided_elem_restriction(ne, q, 1, q * ne, strides) 994*9df49d7eSJed Brown /// .unwrap(); 995*9df49d7eSJed Brown /// 996*9df49d7eSJed Brown /// // Bases 997*9df49d7eSJed Brown /// let bx = ceed 998*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss) 999*9df49d7eSJed Brown /// .unwrap(); 1000*9df49d7eSJed Brown /// let bu = ceed 1001*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, ncomp, p, q, QuadMode::Gauss) 1002*9df49d7eSJed Brown /// .unwrap(); 1003*9df49d7eSJed Brown /// 1004*9df49d7eSJed Brown /// // Build quadrature data 1005*9df49d7eSJed Brown /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild").unwrap(); 1006*9df49d7eSJed Brown /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None) 1007*9df49d7eSJed Brown /// .unwrap() 1008*9df49d7eSJed Brown /// .field("dx", &rx, &bx, VectorOpt::Active) 1009*9df49d7eSJed Brown /// .unwrap() 1010*9df49d7eSJed Brown /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None) 1011*9df49d7eSJed Brown /// .unwrap() 1012*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active) 1013*9df49d7eSJed Brown /// .unwrap() 1014*9df49d7eSJed Brown /// .apply(&x, &mut qdata) 1015*9df49d7eSJed Brown /// .unwrap(); 1016*9df49d7eSJed Brown /// 1017*9df49d7eSJed Brown /// // Mass operator 1018*9df49d7eSJed Brown /// let mut mass_2_comp = |[u, qdata, ..]: QFunctionInputs, [v, ..]: QFunctionOutputs| { 1019*9df49d7eSJed Brown /// // Number of quadrature points 1020*9df49d7eSJed Brown /// let q = qdata.len(); 1021*9df49d7eSJed Brown /// 1022*9df49d7eSJed Brown /// // Iterate over quadrature points 1023*9df49d7eSJed Brown /// for i in 0..q { 1024*9df49d7eSJed Brown /// v[i + 0 * q] = u[i + 1 * q] * qdata[i]; 1025*9df49d7eSJed Brown /// v[i + 1 * q] = u[i + 0 * q] * qdata[i]; 1026*9df49d7eSJed Brown /// } 1027*9df49d7eSJed Brown /// 1028*9df49d7eSJed Brown /// // Return clean error code 1029*9df49d7eSJed Brown /// 0 1030*9df49d7eSJed Brown /// }; 1031*9df49d7eSJed Brown /// 1032*9df49d7eSJed Brown /// let qf_mass = ceed 1033*9df49d7eSJed Brown /// .q_function_interior(1, Box::new(mass_2_comp)) 1034*9df49d7eSJed Brown /// .unwrap() 1035*9df49d7eSJed Brown /// .input("u", 2, EvalMode::Interp) 1036*9df49d7eSJed Brown /// .unwrap() 1037*9df49d7eSJed Brown /// .input("qdata", 1, EvalMode::None) 1038*9df49d7eSJed Brown /// .unwrap() 1039*9df49d7eSJed Brown /// .output("v", 2, EvalMode::Interp) 1040*9df49d7eSJed Brown /// .unwrap(); 1041*9df49d7eSJed Brown /// 1042*9df49d7eSJed Brown /// let op_mass = ceed 1043*9df49d7eSJed Brown /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None) 1044*9df49d7eSJed Brown /// .unwrap() 1045*9df49d7eSJed Brown /// .field("u", &ru, &bu, VectorOpt::Active) 1046*9df49d7eSJed Brown /// .unwrap() 1047*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, &qdata) 1048*9df49d7eSJed Brown /// .unwrap() 1049*9df49d7eSJed Brown /// .field("v", &ru, &bu, VectorOpt::Active) 1050*9df49d7eSJed Brown /// .unwrap(); 1051*9df49d7eSJed Brown /// 1052*9df49d7eSJed Brown /// // Diagonal 1053*9df49d7eSJed Brown /// let mut diag = ceed.vector(ncomp * ncomp * ndofs).unwrap(); 1054*9df49d7eSJed Brown /// diag.set_value(1.0); 1055*9df49d7eSJed Brown /// op_mass 1056*9df49d7eSJed Brown /// .linear_assemble_add_point_block_diagonal(&mut diag) 1057*9df49d7eSJed Brown /// .unwrap(); 1058*9df49d7eSJed Brown /// 1059*9df49d7eSJed Brown /// // Manual diagonal computation 1060*9df49d7eSJed Brown /// let mut true_diag = ceed.vector(ncomp * ncomp * ndofs).unwrap(); 1061*9df49d7eSJed Brown /// for i in 0..ndofs { 1062*9df49d7eSJed Brown /// for j in 0..ncomp { 1063*9df49d7eSJed Brown /// u.set_value(0.0); 1064*9df49d7eSJed Brown /// { 1065*9df49d7eSJed Brown /// let mut u_array = u.view_mut(); 1066*9df49d7eSJed Brown /// u_array[i + j * ndofs] = 1.; 1067*9df49d7eSJed Brown /// } 1068*9df49d7eSJed Brown /// 1069*9df49d7eSJed Brown /// op_mass.apply(&u, &mut v).unwrap(); 1070*9df49d7eSJed Brown /// 1071*9df49d7eSJed Brown /// { 1072*9df49d7eSJed Brown /// let v_array = v.view_mut(); 1073*9df49d7eSJed Brown /// let mut true_array = true_diag.view_mut(); 1074*9df49d7eSJed Brown /// for k in 0..ncomp { 1075*9df49d7eSJed Brown /// true_array[i * ncomp * ncomp + k * ncomp + j] = v_array[i + k * ndofs]; 1076*9df49d7eSJed Brown /// } 1077*9df49d7eSJed Brown /// } 1078*9df49d7eSJed Brown /// } 1079*9df49d7eSJed Brown /// } 1080*9df49d7eSJed Brown /// 1081*9df49d7eSJed Brown /// // Check 1082*9df49d7eSJed Brown /// diag.view() 1083*9df49d7eSJed Brown /// .iter() 1084*9df49d7eSJed Brown /// .zip(true_diag.view().iter()) 1085*9df49d7eSJed Brown /// .for_each(|(computed, actual)| { 1086*9df49d7eSJed Brown /// assert!( 1087*9df49d7eSJed Brown /// (*computed - 1.0 - *actual).abs() < 1e-15, 1088*9df49d7eSJed Brown /// "Diagonal entry incorrect" 1089*9df49d7eSJed Brown /// ); 1090*9df49d7eSJed Brown /// }); 1091*9df49d7eSJed Brown /// ``` 1092*9df49d7eSJed Brown pub fn linear_assemble_add_point_block_diagonal( 1093*9df49d7eSJed Brown &self, 1094*9df49d7eSJed Brown assembled: &mut Vector, 1095*9df49d7eSJed Brown ) -> crate::Result<i32> { 1096*9df49d7eSJed Brown self.op_core 1097*9df49d7eSJed Brown .linear_assemble_add_point_block_diagonal(assembled) 1098*9df49d7eSJed Brown } 1099*9df49d7eSJed Brown 1100*9df49d7eSJed Brown /// Create a multigrid coarse Operator and level transfer Operators for a 1101*9df49d7eSJed Brown /// given Operator, creating the prolongation basis from the fine and 1102*9df49d7eSJed Brown /// coarse grid interpolation 1103*9df49d7eSJed Brown /// 1104*9df49d7eSJed Brown /// * `p_mult_fine` - Lvector multiplicity in parallel gather/scatter 1105*9df49d7eSJed Brown /// * `rstr_coarse` - Coarse grid restriction 1106*9df49d7eSJed Brown /// * `basis_coarse` - Coarse grid active vector basis 1107*9df49d7eSJed Brown /// 1108*9df49d7eSJed Brown /// ``` 1109*9df49d7eSJed Brown /// # use libceed::prelude::*; 1110*9df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 1111*9df49d7eSJed Brown /// let ne = 15; 1112*9df49d7eSJed Brown /// let p_coarse = 3; 1113*9df49d7eSJed Brown /// let p_fine = 5; 1114*9df49d7eSJed Brown /// let q = 6; 1115*9df49d7eSJed Brown /// let ndofs_coarse = p_coarse * ne - ne + 1; 1116*9df49d7eSJed Brown /// let ndofs_fine = p_fine * ne - ne + 1; 1117*9df49d7eSJed Brown /// 1118*9df49d7eSJed Brown /// // Vectors 1119*9df49d7eSJed Brown /// let x_array = (0..ne + 1) 1120*9df49d7eSJed Brown /// .map(|i| 2.0 * i as f64 / ne as f64 - 1.0) 1121*9df49d7eSJed Brown /// .collect::<Vec<f64>>(); 1122*9df49d7eSJed Brown /// let x = ceed.vector_from_slice(&x_array).unwrap(); 1123*9df49d7eSJed Brown /// let mut qdata = ceed.vector(ne * q).unwrap(); 1124*9df49d7eSJed Brown /// qdata.set_value(0.0); 1125*9df49d7eSJed Brown /// let mut u_coarse = ceed.vector(ndofs_coarse).unwrap(); 1126*9df49d7eSJed Brown /// u_coarse.set_value(1.0); 1127*9df49d7eSJed Brown /// let mut u_fine = ceed.vector(ndofs_fine).unwrap(); 1128*9df49d7eSJed Brown /// u_fine.set_value(1.0); 1129*9df49d7eSJed Brown /// let mut v_coarse = ceed.vector(ndofs_coarse).unwrap(); 1130*9df49d7eSJed Brown /// v_coarse.set_value(0.0); 1131*9df49d7eSJed Brown /// let mut v_fine = ceed.vector(ndofs_fine).unwrap(); 1132*9df49d7eSJed Brown /// v_fine.set_value(0.0); 1133*9df49d7eSJed Brown /// let mut multiplicity = ceed.vector(ndofs_fine).unwrap(); 1134*9df49d7eSJed Brown /// multiplicity.set_value(1.0); 1135*9df49d7eSJed Brown /// 1136*9df49d7eSJed Brown /// // Restrictions 1137*9df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 1138*9df49d7eSJed Brown /// let rq = ceed 1139*9df49d7eSJed Brown /// .strided_elem_restriction(ne, q, 1, q * ne, strides) 1140*9df49d7eSJed Brown /// .unwrap(); 1141*9df49d7eSJed Brown /// 1142*9df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 1143*9df49d7eSJed Brown /// for i in 0..ne { 1144*9df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 1145*9df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 1146*9df49d7eSJed Brown /// } 1147*9df49d7eSJed Brown /// let rx = ceed 1148*9df49d7eSJed Brown /// .elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx) 1149*9df49d7eSJed Brown /// .unwrap(); 1150*9df49d7eSJed Brown /// 1151*9df49d7eSJed Brown /// let mut indu_coarse: Vec<i32> = vec![0; p_coarse * ne]; 1152*9df49d7eSJed Brown /// for i in 0..ne { 1153*9df49d7eSJed Brown /// for j in 0..p_coarse { 1154*9df49d7eSJed Brown /// indu_coarse[p_coarse * i + j] = (i + j) as i32; 1155*9df49d7eSJed Brown /// } 1156*9df49d7eSJed Brown /// } 1157*9df49d7eSJed Brown /// let ru_coarse = ceed 1158*9df49d7eSJed Brown /// .elem_restriction( 1159*9df49d7eSJed Brown /// ne, 1160*9df49d7eSJed Brown /// p_coarse, 1161*9df49d7eSJed Brown /// 1, 1162*9df49d7eSJed Brown /// 1, 1163*9df49d7eSJed Brown /// ndofs_coarse, 1164*9df49d7eSJed Brown /// MemType::Host, 1165*9df49d7eSJed Brown /// &indu_coarse, 1166*9df49d7eSJed Brown /// ) 1167*9df49d7eSJed Brown /// .unwrap(); 1168*9df49d7eSJed Brown /// 1169*9df49d7eSJed Brown /// let mut indu_fine: Vec<i32> = vec![0; p_fine * ne]; 1170*9df49d7eSJed Brown /// for i in 0..ne { 1171*9df49d7eSJed Brown /// for j in 0..p_fine { 1172*9df49d7eSJed Brown /// indu_fine[p_fine * i + j] = (i + j) as i32; 1173*9df49d7eSJed Brown /// } 1174*9df49d7eSJed Brown /// } 1175*9df49d7eSJed Brown /// let ru_fine = ceed 1176*9df49d7eSJed Brown /// .elem_restriction(ne, p_fine, 1, 1, ndofs_fine, MemType::Host, &indu_fine) 1177*9df49d7eSJed Brown /// .unwrap(); 1178*9df49d7eSJed Brown /// 1179*9df49d7eSJed Brown /// // Bases 1180*9df49d7eSJed Brown /// let bx = ceed 1181*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss) 1182*9df49d7eSJed Brown /// .unwrap(); 1183*9df49d7eSJed Brown /// let bu_coarse = ceed 1184*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, p_coarse, q, QuadMode::Gauss) 1185*9df49d7eSJed Brown /// .unwrap(); 1186*9df49d7eSJed Brown /// let bu_fine = ceed 1187*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, p_fine, q, QuadMode::Gauss) 1188*9df49d7eSJed Brown /// .unwrap(); 1189*9df49d7eSJed Brown /// 1190*9df49d7eSJed Brown /// // Build quadrature data 1191*9df49d7eSJed Brown /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild").unwrap(); 1192*9df49d7eSJed Brown /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None) 1193*9df49d7eSJed Brown /// .unwrap() 1194*9df49d7eSJed Brown /// .field("dx", &rx, &bx, VectorOpt::Active) 1195*9df49d7eSJed Brown /// .unwrap() 1196*9df49d7eSJed Brown /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None) 1197*9df49d7eSJed Brown /// .unwrap() 1198*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active) 1199*9df49d7eSJed Brown /// .unwrap() 1200*9df49d7eSJed Brown /// .apply(&x, &mut qdata) 1201*9df49d7eSJed Brown /// .unwrap(); 1202*9df49d7eSJed Brown /// 1203*9df49d7eSJed Brown /// // Mass operator 1204*9df49d7eSJed Brown /// let qf_mass = ceed.q_function_interior_by_name("MassApply").unwrap(); 1205*9df49d7eSJed Brown /// let op_mass_fine = ceed 1206*9df49d7eSJed Brown /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None) 1207*9df49d7eSJed Brown /// .unwrap() 1208*9df49d7eSJed Brown /// .field("u", &ru_fine, &bu_fine, VectorOpt::Active) 1209*9df49d7eSJed Brown /// .unwrap() 1210*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, &qdata) 1211*9df49d7eSJed Brown /// .unwrap() 1212*9df49d7eSJed Brown /// .field("v", &ru_fine, &bu_fine, VectorOpt::Active) 1213*9df49d7eSJed Brown /// .unwrap(); 1214*9df49d7eSJed Brown /// 1215*9df49d7eSJed Brown /// // Multigrid setup 1216*9df49d7eSJed Brown /// let (op_mass_coarse, op_prolong, op_restrict) = op_mass_fine 1217*9df49d7eSJed Brown /// .create_multigrid_level(&multiplicity, &ru_coarse, &bu_coarse) 1218*9df49d7eSJed Brown /// .unwrap(); 1219*9df49d7eSJed Brown /// 1220*9df49d7eSJed Brown /// // Coarse problem 1221*9df49d7eSJed Brown /// u_coarse.set_value(1.0); 1222*9df49d7eSJed Brown /// op_mass_coarse.apply(&u_coarse, &mut v_coarse).unwrap(); 1223*9df49d7eSJed Brown /// 1224*9df49d7eSJed Brown /// // Check 1225*9df49d7eSJed Brown /// let sum: f64 = v_coarse.view().iter().sum(); 1226*9df49d7eSJed Brown /// assert!( 1227*9df49d7eSJed Brown /// (sum - 2.0).abs() < 1e-15, 1228*9df49d7eSJed Brown /// "Incorrect interval length computed" 1229*9df49d7eSJed Brown /// ); 1230*9df49d7eSJed Brown /// 1231*9df49d7eSJed Brown /// // Prolong 1232*9df49d7eSJed Brown /// op_prolong.apply(&u_coarse, &mut u_fine).unwrap(); 1233*9df49d7eSJed Brown /// 1234*9df49d7eSJed Brown /// // Fine problem 1235*9df49d7eSJed Brown /// op_mass_fine.apply(&u_fine, &mut v_fine).unwrap(); 1236*9df49d7eSJed Brown /// 1237*9df49d7eSJed Brown /// // Check 1238*9df49d7eSJed Brown /// let sum: f64 = v_fine.view().iter().sum(); 1239*9df49d7eSJed Brown /// assert!( 1240*9df49d7eSJed Brown /// (sum - 2.0).abs() < 1e-15, 1241*9df49d7eSJed Brown /// "Incorrect interval length computed" 1242*9df49d7eSJed Brown /// ); 1243*9df49d7eSJed Brown /// 1244*9df49d7eSJed Brown /// // Restrict 1245*9df49d7eSJed Brown /// op_restrict.apply(&v_fine, &mut v_coarse).unwrap(); 1246*9df49d7eSJed Brown /// 1247*9df49d7eSJed Brown /// // Check 1248*9df49d7eSJed Brown /// let sum: f64 = v_coarse.view().iter().sum(); 1249*9df49d7eSJed Brown /// assert!( 1250*9df49d7eSJed Brown /// (sum - 2.0).abs() < 1e-15, 1251*9df49d7eSJed Brown /// "Incorrect interval length computed" 1252*9df49d7eSJed Brown /// ); 1253*9df49d7eSJed Brown /// ``` 1254*9df49d7eSJed Brown pub fn create_multigrid_level( 1255*9df49d7eSJed Brown &self, 1256*9df49d7eSJed Brown p_mult_fine: &Vector, 1257*9df49d7eSJed Brown rstr_coarse: &ElemRestriction, 1258*9df49d7eSJed Brown basis_coarse: &Basis, 1259*9df49d7eSJed Brown ) -> crate::Result<(Operator, Operator, Operator)> { 1260*9df49d7eSJed Brown let mut ptr_coarse = std::ptr::null_mut(); 1261*9df49d7eSJed Brown let mut ptr_prolong = std::ptr::null_mut(); 1262*9df49d7eSJed Brown let mut ptr_restrict = std::ptr::null_mut(); 1263*9df49d7eSJed Brown let ierr = unsafe { 1264*9df49d7eSJed Brown bind_ceed::CeedOperatorMultigridLevelCreate( 1265*9df49d7eSJed Brown self.op_core.ptr, 1266*9df49d7eSJed Brown p_mult_fine.ptr, 1267*9df49d7eSJed Brown rstr_coarse.ptr, 1268*9df49d7eSJed Brown basis_coarse.ptr, 1269*9df49d7eSJed Brown &mut ptr_coarse, 1270*9df49d7eSJed Brown &mut ptr_prolong, 1271*9df49d7eSJed Brown &mut ptr_restrict, 1272*9df49d7eSJed Brown ) 1273*9df49d7eSJed Brown }; 1274*9df49d7eSJed Brown self.op_core.ceed.check_error(ierr)?; 1275*9df49d7eSJed Brown let op_coarse = Operator::from_raw(self.op_core.ceed, ptr_coarse)?; 1276*9df49d7eSJed Brown let op_prolong = Operator::from_raw(self.op_core.ceed, ptr_prolong)?; 1277*9df49d7eSJed Brown let op_restrict = Operator::from_raw(self.op_core.ceed, ptr_restrict)?; 1278*9df49d7eSJed Brown Ok((op_coarse, op_prolong, op_restrict)) 1279*9df49d7eSJed Brown } 1280*9df49d7eSJed Brown 1281*9df49d7eSJed Brown /// Create a multigrid coarse Operator and level transfer Operators for a 1282*9df49d7eSJed Brown /// given Operator with a tensor basis for the active basis 1283*9df49d7eSJed Brown /// 1284*9df49d7eSJed Brown /// * `p_mult_fine` - Lvector multiplicity in parallel gather/scatter 1285*9df49d7eSJed Brown /// * `rstr_coarse` - Coarse grid restriction 1286*9df49d7eSJed Brown /// * `basis_coarse` - Coarse grid active vector basis 1287*9df49d7eSJed Brown /// * `interp_c_to_f` - Matrix for coarse to fine 1288*9df49d7eSJed Brown /// 1289*9df49d7eSJed Brown /// ``` 1290*9df49d7eSJed Brown /// # use libceed::prelude::*; 1291*9df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 1292*9df49d7eSJed Brown /// let ne = 15; 1293*9df49d7eSJed Brown /// let p_coarse = 3; 1294*9df49d7eSJed Brown /// let p_fine = 5; 1295*9df49d7eSJed Brown /// let q = 6; 1296*9df49d7eSJed Brown /// let ndofs_coarse = p_coarse * ne - ne + 1; 1297*9df49d7eSJed Brown /// let ndofs_fine = p_fine * ne - ne + 1; 1298*9df49d7eSJed Brown /// 1299*9df49d7eSJed Brown /// // Vectors 1300*9df49d7eSJed Brown /// let x_array = (0..ne + 1) 1301*9df49d7eSJed Brown /// .map(|i| 2.0 * i as f64 / ne as f64 - 1.0) 1302*9df49d7eSJed Brown /// .collect::<Vec<f64>>(); 1303*9df49d7eSJed Brown /// let x = ceed.vector_from_slice(&x_array).unwrap(); 1304*9df49d7eSJed Brown /// let mut qdata = ceed.vector(ne * q).unwrap(); 1305*9df49d7eSJed Brown /// qdata.set_value(0.0); 1306*9df49d7eSJed Brown /// let mut u_coarse = ceed.vector(ndofs_coarse).unwrap(); 1307*9df49d7eSJed Brown /// u_coarse.set_value(1.0); 1308*9df49d7eSJed Brown /// let mut u_fine = ceed.vector(ndofs_fine).unwrap(); 1309*9df49d7eSJed Brown /// u_fine.set_value(1.0); 1310*9df49d7eSJed Brown /// let mut v_coarse = ceed.vector(ndofs_coarse).unwrap(); 1311*9df49d7eSJed Brown /// v_coarse.set_value(0.0); 1312*9df49d7eSJed Brown /// let mut v_fine = ceed.vector(ndofs_fine).unwrap(); 1313*9df49d7eSJed Brown /// v_fine.set_value(0.0); 1314*9df49d7eSJed Brown /// let mut multiplicity = ceed.vector(ndofs_fine).unwrap(); 1315*9df49d7eSJed Brown /// multiplicity.set_value(1.0); 1316*9df49d7eSJed Brown /// 1317*9df49d7eSJed Brown /// // Restrictions 1318*9df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 1319*9df49d7eSJed Brown /// let rq = ceed 1320*9df49d7eSJed Brown /// .strided_elem_restriction(ne, q, 1, q * ne, strides) 1321*9df49d7eSJed Brown /// .unwrap(); 1322*9df49d7eSJed Brown /// 1323*9df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 1324*9df49d7eSJed Brown /// for i in 0..ne { 1325*9df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 1326*9df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 1327*9df49d7eSJed Brown /// } 1328*9df49d7eSJed Brown /// let rx = ceed 1329*9df49d7eSJed Brown /// .elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx) 1330*9df49d7eSJed Brown /// .unwrap(); 1331*9df49d7eSJed Brown /// 1332*9df49d7eSJed Brown /// let mut indu_coarse: Vec<i32> = vec![0; p_coarse * ne]; 1333*9df49d7eSJed Brown /// for i in 0..ne { 1334*9df49d7eSJed Brown /// for j in 0..p_coarse { 1335*9df49d7eSJed Brown /// indu_coarse[p_coarse * i + j] = (i + j) as i32; 1336*9df49d7eSJed Brown /// } 1337*9df49d7eSJed Brown /// } 1338*9df49d7eSJed Brown /// let ru_coarse = ceed 1339*9df49d7eSJed Brown /// .elem_restriction( 1340*9df49d7eSJed Brown /// ne, 1341*9df49d7eSJed Brown /// p_coarse, 1342*9df49d7eSJed Brown /// 1, 1343*9df49d7eSJed Brown /// 1, 1344*9df49d7eSJed Brown /// ndofs_coarse, 1345*9df49d7eSJed Brown /// MemType::Host, 1346*9df49d7eSJed Brown /// &indu_coarse, 1347*9df49d7eSJed Brown /// ) 1348*9df49d7eSJed Brown /// .unwrap(); 1349*9df49d7eSJed Brown /// 1350*9df49d7eSJed Brown /// let mut indu_fine: Vec<i32> = vec![0; p_fine * ne]; 1351*9df49d7eSJed Brown /// for i in 0..ne { 1352*9df49d7eSJed Brown /// for j in 0..p_fine { 1353*9df49d7eSJed Brown /// indu_fine[p_fine * i + j] = (i + j) as i32; 1354*9df49d7eSJed Brown /// } 1355*9df49d7eSJed Brown /// } 1356*9df49d7eSJed Brown /// let ru_fine = ceed 1357*9df49d7eSJed Brown /// .elem_restriction(ne, p_fine, 1, 1, ndofs_fine, MemType::Host, &indu_fine) 1358*9df49d7eSJed Brown /// .unwrap(); 1359*9df49d7eSJed Brown /// 1360*9df49d7eSJed Brown /// // Bases 1361*9df49d7eSJed Brown /// let bx = ceed 1362*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss) 1363*9df49d7eSJed Brown /// .unwrap(); 1364*9df49d7eSJed Brown /// let bu_coarse = ceed 1365*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, p_coarse, q, QuadMode::Gauss) 1366*9df49d7eSJed Brown /// .unwrap(); 1367*9df49d7eSJed Brown /// let bu_fine = ceed 1368*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, p_fine, q, QuadMode::Gauss) 1369*9df49d7eSJed Brown /// .unwrap(); 1370*9df49d7eSJed Brown /// 1371*9df49d7eSJed Brown /// // Build quadrature data 1372*9df49d7eSJed Brown /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild").unwrap(); 1373*9df49d7eSJed Brown /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None) 1374*9df49d7eSJed Brown /// .unwrap() 1375*9df49d7eSJed Brown /// .field("dx", &rx, &bx, VectorOpt::Active) 1376*9df49d7eSJed Brown /// .unwrap() 1377*9df49d7eSJed Brown /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None) 1378*9df49d7eSJed Brown /// .unwrap() 1379*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active) 1380*9df49d7eSJed Brown /// .unwrap() 1381*9df49d7eSJed Brown /// .apply(&x, &mut qdata) 1382*9df49d7eSJed Brown /// .unwrap(); 1383*9df49d7eSJed Brown /// 1384*9df49d7eSJed Brown /// // Mass operator 1385*9df49d7eSJed Brown /// let qf_mass = ceed.q_function_interior_by_name("MassApply").unwrap(); 1386*9df49d7eSJed Brown /// let op_mass_fine = ceed 1387*9df49d7eSJed Brown /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None) 1388*9df49d7eSJed Brown /// .unwrap() 1389*9df49d7eSJed Brown /// .field("u", &ru_fine, &bu_fine, VectorOpt::Active) 1390*9df49d7eSJed Brown /// .unwrap() 1391*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, &qdata) 1392*9df49d7eSJed Brown /// .unwrap() 1393*9df49d7eSJed Brown /// .field("v", &ru_fine, &bu_fine, VectorOpt::Active) 1394*9df49d7eSJed Brown /// .unwrap(); 1395*9df49d7eSJed Brown /// 1396*9df49d7eSJed Brown /// // Multigrid setup 1397*9df49d7eSJed Brown /// let mut interp_c_to_f: Vec<f64> = vec![0.; p_coarse * p_fine]; 1398*9df49d7eSJed Brown /// { 1399*9df49d7eSJed Brown /// let mut coarse = ceed.vector(p_coarse).unwrap(); 1400*9df49d7eSJed Brown /// let mut fine = ceed.vector(p_fine).unwrap(); 1401*9df49d7eSJed Brown /// let basis_c_to_f = ceed 1402*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, p_coarse, p_fine, QuadMode::GaussLobatto) 1403*9df49d7eSJed Brown /// .unwrap(); 1404*9df49d7eSJed Brown /// for i in 0..p_coarse { 1405*9df49d7eSJed Brown /// coarse.set_value(0.0); 1406*9df49d7eSJed Brown /// { 1407*9df49d7eSJed Brown /// let mut array = coarse.view_mut(); 1408*9df49d7eSJed Brown /// array[i] = 1.; 1409*9df49d7eSJed Brown /// } 1410*9df49d7eSJed Brown /// basis_c_to_f 1411*9df49d7eSJed Brown /// .apply( 1412*9df49d7eSJed Brown /// 1, 1413*9df49d7eSJed Brown /// TransposeMode::NoTranspose, 1414*9df49d7eSJed Brown /// EvalMode::Interp, 1415*9df49d7eSJed Brown /// &coarse, 1416*9df49d7eSJed Brown /// &mut fine, 1417*9df49d7eSJed Brown /// ) 1418*9df49d7eSJed Brown /// .unwrap(); 1419*9df49d7eSJed Brown /// let array = fine.view(); 1420*9df49d7eSJed Brown /// for j in 0..p_fine { 1421*9df49d7eSJed Brown /// interp_c_to_f[j * p_coarse + i] = array[j]; 1422*9df49d7eSJed Brown /// } 1423*9df49d7eSJed Brown /// } 1424*9df49d7eSJed Brown /// } 1425*9df49d7eSJed Brown /// let (op_mass_coarse, op_prolong, op_restrict) = op_mass_fine 1426*9df49d7eSJed Brown /// .create_multigrid_level_tensor_H1(&multiplicity, &ru_coarse, &bu_coarse, &interp_c_to_f) 1427*9df49d7eSJed Brown /// .unwrap(); 1428*9df49d7eSJed Brown /// 1429*9df49d7eSJed Brown /// // Coarse problem 1430*9df49d7eSJed Brown /// u_coarse.set_value(1.0); 1431*9df49d7eSJed Brown /// op_mass_coarse.apply(&u_coarse, &mut v_coarse).unwrap(); 1432*9df49d7eSJed Brown /// 1433*9df49d7eSJed Brown /// // Check 1434*9df49d7eSJed Brown /// let sum: f64 = v_coarse.view().iter().sum(); 1435*9df49d7eSJed Brown /// assert!( 1436*9df49d7eSJed Brown /// (sum - 2.0).abs() < 1e-15, 1437*9df49d7eSJed Brown /// "Incorrect interval length computed" 1438*9df49d7eSJed Brown /// ); 1439*9df49d7eSJed Brown /// 1440*9df49d7eSJed Brown /// // Prolong 1441*9df49d7eSJed Brown /// op_prolong.apply(&u_coarse, &mut u_fine).unwrap(); 1442*9df49d7eSJed Brown /// 1443*9df49d7eSJed Brown /// // Fine problem 1444*9df49d7eSJed Brown /// op_mass_fine.apply(&u_fine, &mut v_fine).unwrap(); 1445*9df49d7eSJed Brown /// 1446*9df49d7eSJed Brown /// // Check 1447*9df49d7eSJed Brown /// let sum: f64 = v_fine.view().iter().sum(); 1448*9df49d7eSJed Brown /// assert!( 1449*9df49d7eSJed Brown /// (sum - 2.0).abs() < 1e-15, 1450*9df49d7eSJed Brown /// "Incorrect interval length computed" 1451*9df49d7eSJed Brown /// ); 1452*9df49d7eSJed Brown /// 1453*9df49d7eSJed Brown /// // Restrict 1454*9df49d7eSJed Brown /// op_restrict.apply(&v_fine, &mut v_coarse).unwrap(); 1455*9df49d7eSJed Brown /// 1456*9df49d7eSJed Brown /// // Check 1457*9df49d7eSJed Brown /// let sum: f64 = v_coarse.view().iter().sum(); 1458*9df49d7eSJed Brown /// assert!( 1459*9df49d7eSJed Brown /// (sum - 2.0).abs() < 1e-15, 1460*9df49d7eSJed Brown /// "Incorrect interval length computed" 1461*9df49d7eSJed Brown /// ); 1462*9df49d7eSJed Brown /// ``` 1463*9df49d7eSJed Brown pub fn create_multigrid_level_tensor_H1( 1464*9df49d7eSJed Brown &self, 1465*9df49d7eSJed Brown p_mult_fine: &Vector, 1466*9df49d7eSJed Brown rstr_coarse: &ElemRestriction, 1467*9df49d7eSJed Brown basis_coarse: &Basis, 1468*9df49d7eSJed Brown interpCtoF: &Vec<f64>, 1469*9df49d7eSJed Brown ) -> crate::Result<(Operator, Operator, Operator)> { 1470*9df49d7eSJed Brown let mut ptr_coarse = std::ptr::null_mut(); 1471*9df49d7eSJed Brown let mut ptr_prolong = std::ptr::null_mut(); 1472*9df49d7eSJed Brown let mut ptr_restrict = std::ptr::null_mut(); 1473*9df49d7eSJed Brown let ierr = unsafe { 1474*9df49d7eSJed Brown bind_ceed::CeedOperatorMultigridLevelCreateTensorH1( 1475*9df49d7eSJed Brown self.op_core.ptr, 1476*9df49d7eSJed Brown p_mult_fine.ptr, 1477*9df49d7eSJed Brown rstr_coarse.ptr, 1478*9df49d7eSJed Brown basis_coarse.ptr, 1479*9df49d7eSJed Brown interpCtoF.as_ptr(), 1480*9df49d7eSJed Brown &mut ptr_coarse, 1481*9df49d7eSJed Brown &mut ptr_prolong, 1482*9df49d7eSJed Brown &mut ptr_restrict, 1483*9df49d7eSJed Brown ) 1484*9df49d7eSJed Brown }; 1485*9df49d7eSJed Brown self.op_core.ceed.check_error(ierr)?; 1486*9df49d7eSJed Brown let op_coarse = Operator::from_raw(self.op_core.ceed, ptr_coarse)?; 1487*9df49d7eSJed Brown let op_prolong = Operator::from_raw(self.op_core.ceed, ptr_prolong)?; 1488*9df49d7eSJed Brown let op_restrict = Operator::from_raw(self.op_core.ceed, ptr_restrict)?; 1489*9df49d7eSJed Brown Ok((op_coarse, op_prolong, op_restrict)) 1490*9df49d7eSJed Brown } 1491*9df49d7eSJed Brown 1492*9df49d7eSJed Brown /// Create a multigrid coarse Operator and level transfer Operators for a 1493*9df49d7eSJed Brown /// given Operator with a non-tensor basis for the active basis 1494*9df49d7eSJed Brown /// 1495*9df49d7eSJed Brown /// * `p_mult_fine` - Lvector multiplicity in parallel gather/scatter 1496*9df49d7eSJed Brown /// * `rstr_coarse` - Coarse grid restriction 1497*9df49d7eSJed Brown /// * `basis_coarse` - Coarse grid active vector basis 1498*9df49d7eSJed Brown /// * `interp_c_to_f` - Matrix for coarse to fine 1499*9df49d7eSJed Brown /// 1500*9df49d7eSJed Brown /// ``` 1501*9df49d7eSJed Brown /// # use libceed::prelude::*; 1502*9df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 1503*9df49d7eSJed Brown /// let ne = 15; 1504*9df49d7eSJed Brown /// let p_coarse = 3; 1505*9df49d7eSJed Brown /// let p_fine = 5; 1506*9df49d7eSJed Brown /// let q = 6; 1507*9df49d7eSJed Brown /// let ndofs_coarse = p_coarse * ne - ne + 1; 1508*9df49d7eSJed Brown /// let ndofs_fine = p_fine * ne - ne + 1; 1509*9df49d7eSJed Brown /// 1510*9df49d7eSJed Brown /// // Vectors 1511*9df49d7eSJed Brown /// let x_array = (0..ne + 1) 1512*9df49d7eSJed Brown /// .map(|i| 2.0 * i as f64 / ne as f64 - 1.0) 1513*9df49d7eSJed Brown /// .collect::<Vec<f64>>(); 1514*9df49d7eSJed Brown /// let x = ceed.vector_from_slice(&x_array).unwrap(); 1515*9df49d7eSJed Brown /// let mut qdata = ceed.vector(ne * q).unwrap(); 1516*9df49d7eSJed Brown /// qdata.set_value(0.0); 1517*9df49d7eSJed Brown /// let mut u_coarse = ceed.vector(ndofs_coarse).unwrap(); 1518*9df49d7eSJed Brown /// u_coarse.set_value(1.0); 1519*9df49d7eSJed Brown /// let mut u_fine = ceed.vector(ndofs_fine).unwrap(); 1520*9df49d7eSJed Brown /// u_fine.set_value(1.0); 1521*9df49d7eSJed Brown /// let mut v_coarse = ceed.vector(ndofs_coarse).unwrap(); 1522*9df49d7eSJed Brown /// v_coarse.set_value(0.0); 1523*9df49d7eSJed Brown /// let mut v_fine = ceed.vector(ndofs_fine).unwrap(); 1524*9df49d7eSJed Brown /// v_fine.set_value(0.0); 1525*9df49d7eSJed Brown /// let mut multiplicity = ceed.vector(ndofs_fine).unwrap(); 1526*9df49d7eSJed Brown /// multiplicity.set_value(1.0); 1527*9df49d7eSJed Brown /// 1528*9df49d7eSJed Brown /// // Restrictions 1529*9df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 1530*9df49d7eSJed Brown /// let rq = ceed 1531*9df49d7eSJed Brown /// .strided_elem_restriction(ne, q, 1, q * ne, strides) 1532*9df49d7eSJed Brown /// .unwrap(); 1533*9df49d7eSJed Brown /// 1534*9df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 1535*9df49d7eSJed Brown /// for i in 0..ne { 1536*9df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 1537*9df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 1538*9df49d7eSJed Brown /// } 1539*9df49d7eSJed Brown /// let rx = ceed 1540*9df49d7eSJed Brown /// .elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx) 1541*9df49d7eSJed Brown /// .unwrap(); 1542*9df49d7eSJed Brown /// 1543*9df49d7eSJed Brown /// let mut indu_coarse: Vec<i32> = vec![0; p_coarse * ne]; 1544*9df49d7eSJed Brown /// for i in 0..ne { 1545*9df49d7eSJed Brown /// for j in 0..p_coarse { 1546*9df49d7eSJed Brown /// indu_coarse[p_coarse * i + j] = (i + j) as i32; 1547*9df49d7eSJed Brown /// } 1548*9df49d7eSJed Brown /// } 1549*9df49d7eSJed Brown /// let ru_coarse = ceed 1550*9df49d7eSJed Brown /// .elem_restriction( 1551*9df49d7eSJed Brown /// ne, 1552*9df49d7eSJed Brown /// p_coarse, 1553*9df49d7eSJed Brown /// 1, 1554*9df49d7eSJed Brown /// 1, 1555*9df49d7eSJed Brown /// ndofs_coarse, 1556*9df49d7eSJed Brown /// MemType::Host, 1557*9df49d7eSJed Brown /// &indu_coarse, 1558*9df49d7eSJed Brown /// ) 1559*9df49d7eSJed Brown /// .unwrap(); 1560*9df49d7eSJed Brown /// 1561*9df49d7eSJed Brown /// let mut indu_fine: Vec<i32> = vec![0; p_fine * ne]; 1562*9df49d7eSJed Brown /// for i in 0..ne { 1563*9df49d7eSJed Brown /// for j in 0..p_fine { 1564*9df49d7eSJed Brown /// indu_fine[p_fine * i + j] = (i + j) as i32; 1565*9df49d7eSJed Brown /// } 1566*9df49d7eSJed Brown /// } 1567*9df49d7eSJed Brown /// let ru_fine = ceed 1568*9df49d7eSJed Brown /// .elem_restriction(ne, p_fine, 1, 1, ndofs_fine, MemType::Host, &indu_fine) 1569*9df49d7eSJed Brown /// .unwrap(); 1570*9df49d7eSJed Brown /// 1571*9df49d7eSJed Brown /// // Bases 1572*9df49d7eSJed Brown /// let bx = ceed 1573*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss) 1574*9df49d7eSJed Brown /// .unwrap(); 1575*9df49d7eSJed Brown /// let bu_coarse = ceed 1576*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, p_coarse, q, QuadMode::Gauss) 1577*9df49d7eSJed Brown /// .unwrap(); 1578*9df49d7eSJed Brown /// let bu_fine = ceed 1579*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, p_fine, q, QuadMode::Gauss) 1580*9df49d7eSJed Brown /// .unwrap(); 1581*9df49d7eSJed Brown /// 1582*9df49d7eSJed Brown /// // Build quadrature data 1583*9df49d7eSJed Brown /// let qf_build = ceed.q_function_interior_by_name("Mass1DBuild").unwrap(); 1584*9df49d7eSJed Brown /// ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None) 1585*9df49d7eSJed Brown /// .unwrap() 1586*9df49d7eSJed Brown /// .field("dx", &rx, &bx, VectorOpt::Active) 1587*9df49d7eSJed Brown /// .unwrap() 1588*9df49d7eSJed Brown /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None) 1589*9df49d7eSJed Brown /// .unwrap() 1590*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active) 1591*9df49d7eSJed Brown /// .unwrap() 1592*9df49d7eSJed Brown /// .apply(&x, &mut qdata) 1593*9df49d7eSJed Brown /// .unwrap(); 1594*9df49d7eSJed Brown /// 1595*9df49d7eSJed Brown /// // Mass operator 1596*9df49d7eSJed Brown /// let qf_mass = ceed.q_function_interior_by_name("MassApply").unwrap(); 1597*9df49d7eSJed Brown /// let op_mass_fine = ceed 1598*9df49d7eSJed Brown /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None) 1599*9df49d7eSJed Brown /// .unwrap() 1600*9df49d7eSJed Brown /// .field("u", &ru_fine, &bu_fine, VectorOpt::Active) 1601*9df49d7eSJed Brown /// .unwrap() 1602*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, &qdata) 1603*9df49d7eSJed Brown /// .unwrap() 1604*9df49d7eSJed Brown /// .field("v", &ru_fine, &bu_fine, VectorOpt::Active) 1605*9df49d7eSJed Brown /// .unwrap(); 1606*9df49d7eSJed Brown /// 1607*9df49d7eSJed Brown /// // Multigrid setup 1608*9df49d7eSJed Brown /// let mut interp_c_to_f: Vec<f64> = vec![0.; p_coarse * p_fine]; 1609*9df49d7eSJed Brown /// { 1610*9df49d7eSJed Brown /// let mut coarse = ceed.vector(p_coarse).unwrap(); 1611*9df49d7eSJed Brown /// let mut fine = ceed.vector(p_fine).unwrap(); 1612*9df49d7eSJed Brown /// let basis_c_to_f = ceed 1613*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, p_coarse, p_fine, QuadMode::GaussLobatto) 1614*9df49d7eSJed Brown /// .unwrap(); 1615*9df49d7eSJed Brown /// for i in 0..p_coarse { 1616*9df49d7eSJed Brown /// coarse.set_value(0.0); 1617*9df49d7eSJed Brown /// { 1618*9df49d7eSJed Brown /// let mut array = coarse.view_mut(); 1619*9df49d7eSJed Brown /// array[i] = 1.; 1620*9df49d7eSJed Brown /// } 1621*9df49d7eSJed Brown /// basis_c_to_f 1622*9df49d7eSJed Brown /// .apply( 1623*9df49d7eSJed Brown /// 1, 1624*9df49d7eSJed Brown /// TransposeMode::NoTranspose, 1625*9df49d7eSJed Brown /// EvalMode::Interp, 1626*9df49d7eSJed Brown /// &coarse, 1627*9df49d7eSJed Brown /// &mut fine, 1628*9df49d7eSJed Brown /// ) 1629*9df49d7eSJed Brown /// .unwrap(); 1630*9df49d7eSJed Brown /// let array = fine.view(); 1631*9df49d7eSJed Brown /// for j in 0..p_fine { 1632*9df49d7eSJed Brown /// interp_c_to_f[j * p_coarse + i] = array[j]; 1633*9df49d7eSJed Brown /// } 1634*9df49d7eSJed Brown /// } 1635*9df49d7eSJed Brown /// } 1636*9df49d7eSJed Brown /// let (op_mass_coarse, op_prolong, op_restrict) = op_mass_fine 1637*9df49d7eSJed Brown /// .create_multigrid_level_H1(&multiplicity, &ru_coarse, &bu_coarse, &interp_c_to_f) 1638*9df49d7eSJed Brown /// .unwrap(); 1639*9df49d7eSJed Brown /// 1640*9df49d7eSJed Brown /// // Coarse problem 1641*9df49d7eSJed Brown /// u_coarse.set_value(1.0); 1642*9df49d7eSJed Brown /// op_mass_coarse.apply(&u_coarse, &mut v_coarse).unwrap(); 1643*9df49d7eSJed Brown /// 1644*9df49d7eSJed Brown /// // Check 1645*9df49d7eSJed Brown /// let sum: f64 = v_coarse.view().iter().sum(); 1646*9df49d7eSJed Brown /// assert!( 1647*9df49d7eSJed Brown /// (sum - 2.0).abs() < 1e-15, 1648*9df49d7eSJed Brown /// "Incorrect interval length computed" 1649*9df49d7eSJed Brown /// ); 1650*9df49d7eSJed Brown /// 1651*9df49d7eSJed Brown /// // Prolong 1652*9df49d7eSJed Brown /// op_prolong.apply(&u_coarse, &mut u_fine).unwrap(); 1653*9df49d7eSJed Brown /// 1654*9df49d7eSJed Brown /// // Fine problem 1655*9df49d7eSJed Brown /// op_mass_fine.apply(&u_fine, &mut v_fine).unwrap(); 1656*9df49d7eSJed Brown /// 1657*9df49d7eSJed Brown /// // Check 1658*9df49d7eSJed Brown /// let sum: f64 = v_fine.view().iter().sum(); 1659*9df49d7eSJed Brown /// assert!( 1660*9df49d7eSJed Brown /// (sum - 2.0).abs() < 1e-15, 1661*9df49d7eSJed Brown /// "Incorrect interval length computed" 1662*9df49d7eSJed Brown /// ); 1663*9df49d7eSJed Brown /// 1664*9df49d7eSJed Brown /// // Restrict 1665*9df49d7eSJed Brown /// op_restrict.apply(&v_fine, &mut v_coarse).unwrap(); 1666*9df49d7eSJed Brown /// 1667*9df49d7eSJed Brown /// // Check 1668*9df49d7eSJed Brown /// let sum: f64 = v_coarse.view().iter().sum(); 1669*9df49d7eSJed Brown /// assert!( 1670*9df49d7eSJed Brown /// (sum - 2.0).abs() < 1e-15, 1671*9df49d7eSJed Brown /// "Incorrect interval length computed" 1672*9df49d7eSJed Brown /// ); 1673*9df49d7eSJed Brown /// ``` 1674*9df49d7eSJed Brown pub fn create_multigrid_level_H1( 1675*9df49d7eSJed Brown &self, 1676*9df49d7eSJed Brown p_mult_fine: &Vector, 1677*9df49d7eSJed Brown rstr_coarse: &ElemRestriction, 1678*9df49d7eSJed Brown basis_coarse: &Basis, 1679*9df49d7eSJed Brown interpCtoF: &[f64], 1680*9df49d7eSJed Brown ) -> crate::Result<(Operator, Operator, Operator)> { 1681*9df49d7eSJed Brown let mut ptr_coarse = std::ptr::null_mut(); 1682*9df49d7eSJed Brown let mut ptr_prolong = std::ptr::null_mut(); 1683*9df49d7eSJed Brown let mut ptr_restrict = std::ptr::null_mut(); 1684*9df49d7eSJed Brown let ierr = unsafe { 1685*9df49d7eSJed Brown bind_ceed::CeedOperatorMultigridLevelCreateH1( 1686*9df49d7eSJed Brown self.op_core.ptr, 1687*9df49d7eSJed Brown p_mult_fine.ptr, 1688*9df49d7eSJed Brown rstr_coarse.ptr, 1689*9df49d7eSJed Brown basis_coarse.ptr, 1690*9df49d7eSJed Brown interpCtoF.as_ptr(), 1691*9df49d7eSJed Brown &mut ptr_coarse, 1692*9df49d7eSJed Brown &mut ptr_prolong, 1693*9df49d7eSJed Brown &mut ptr_restrict, 1694*9df49d7eSJed Brown ) 1695*9df49d7eSJed Brown }; 1696*9df49d7eSJed Brown self.op_core.ceed.check_error(ierr)?; 1697*9df49d7eSJed Brown let op_coarse = Operator::from_raw(self.op_core.ceed, ptr_coarse)?; 1698*9df49d7eSJed Brown let op_prolong = Operator::from_raw(self.op_core.ceed, ptr_prolong)?; 1699*9df49d7eSJed Brown let op_restrict = Operator::from_raw(self.op_core.ceed, ptr_restrict)?; 1700*9df49d7eSJed Brown Ok((op_coarse, op_prolong, op_restrict)) 1701*9df49d7eSJed Brown } 1702*9df49d7eSJed Brown } 1703*9df49d7eSJed Brown 1704*9df49d7eSJed Brown // ----------------------------------------------------------------------------- 1705*9df49d7eSJed Brown // Composite Operator 1706*9df49d7eSJed Brown // ----------------------------------------------------------------------------- 1707*9df49d7eSJed Brown impl<'a> CompositeOperator<'a> { 1708*9df49d7eSJed Brown // Constructor 1709*9df49d7eSJed Brown pub fn create(ceed: &'a crate::Ceed) -> crate::Result<Self> { 1710*9df49d7eSJed Brown let mut ptr = std::ptr::null_mut(); 1711*9df49d7eSJed Brown let ierr = unsafe { bind_ceed::CeedCompositeOperatorCreate(ceed.ptr, &mut ptr) }; 1712*9df49d7eSJed Brown ceed.check_error(ierr)?; 1713*9df49d7eSJed Brown Ok(Self { 1714*9df49d7eSJed Brown op_core: OperatorCore { ceed, ptr }, 1715*9df49d7eSJed Brown }) 1716*9df49d7eSJed Brown } 1717*9df49d7eSJed Brown 1718*9df49d7eSJed Brown /// Apply Operator to a vector 1719*9df49d7eSJed Brown /// 1720*9df49d7eSJed Brown /// * `input` - Input Vector 1721*9df49d7eSJed Brown /// * `output` - Output Vector 1722*9df49d7eSJed Brown /// 1723*9df49d7eSJed Brown /// ``` 1724*9df49d7eSJed Brown /// # use libceed::prelude::*; 1725*9df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 1726*9df49d7eSJed Brown /// let ne = 4; 1727*9df49d7eSJed Brown /// let p = 3; 1728*9df49d7eSJed Brown /// let q = 4; 1729*9df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 1730*9df49d7eSJed Brown /// 1731*9df49d7eSJed Brown /// // Vectors 1732*9df49d7eSJed Brown /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0]).unwrap(); 1733*9df49d7eSJed Brown /// let mut qdata_mass = ceed.vector(ne * q).unwrap(); 1734*9df49d7eSJed Brown /// qdata_mass.set_value(0.0); 1735*9df49d7eSJed Brown /// let mut qdata_diff = ceed.vector(ne * q).unwrap(); 1736*9df49d7eSJed Brown /// qdata_diff.set_value(0.0); 1737*9df49d7eSJed Brown /// let mut u = ceed.vector(ndofs).unwrap(); 1738*9df49d7eSJed Brown /// u.set_value(1.0); 1739*9df49d7eSJed Brown /// let mut v = ceed.vector(ndofs).unwrap(); 1740*9df49d7eSJed Brown /// v.set_value(0.0); 1741*9df49d7eSJed Brown /// 1742*9df49d7eSJed Brown /// // Restrictions 1743*9df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 1744*9df49d7eSJed Brown /// for i in 0..ne { 1745*9df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 1746*9df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 1747*9df49d7eSJed Brown /// } 1748*9df49d7eSJed Brown /// let rx = ceed 1749*9df49d7eSJed Brown /// .elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx) 1750*9df49d7eSJed Brown /// .unwrap(); 1751*9df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 1752*9df49d7eSJed Brown /// for i in 0..ne { 1753*9df49d7eSJed Brown /// indu[p * i + 0] = i as i32; 1754*9df49d7eSJed Brown /// indu[p * i + 1] = (i + 1) as i32; 1755*9df49d7eSJed Brown /// indu[p * i + 2] = (i + 2) as i32; 1756*9df49d7eSJed Brown /// } 1757*9df49d7eSJed Brown /// let ru = ceed 1758*9df49d7eSJed Brown /// .elem_restriction(ne, 3, 1, 1, ndofs, MemType::Host, &indu) 1759*9df49d7eSJed Brown /// .unwrap(); 1760*9df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 1761*9df49d7eSJed Brown /// let rq = ceed 1762*9df49d7eSJed Brown /// .strided_elem_restriction(ne, q, 1, q * ne, strides) 1763*9df49d7eSJed Brown /// .unwrap(); 1764*9df49d7eSJed Brown /// 1765*9df49d7eSJed Brown /// // Bases 1766*9df49d7eSJed Brown /// let bx = ceed 1767*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss) 1768*9df49d7eSJed Brown /// .unwrap(); 1769*9df49d7eSJed Brown /// let bu = ceed 1770*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, p, q, QuadMode::Gauss) 1771*9df49d7eSJed Brown /// .unwrap(); 1772*9df49d7eSJed Brown /// 1773*9df49d7eSJed Brown /// // Build quadrature data 1774*9df49d7eSJed Brown /// let qf_build_mass = ceed.q_function_interior_by_name("Mass1DBuild").unwrap(); 1775*9df49d7eSJed Brown /// ceed.operator(&qf_build_mass, QFunctionOpt::None, QFunctionOpt::None) 1776*9df49d7eSJed Brown /// .unwrap() 1777*9df49d7eSJed Brown /// .field("dx", &rx, &bx, VectorOpt::Active) 1778*9df49d7eSJed Brown /// .unwrap() 1779*9df49d7eSJed Brown /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None) 1780*9df49d7eSJed Brown /// .unwrap() 1781*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active) 1782*9df49d7eSJed Brown /// .unwrap() 1783*9df49d7eSJed Brown /// .apply(&x, &mut qdata_mass) 1784*9df49d7eSJed Brown /// .unwrap(); 1785*9df49d7eSJed Brown /// 1786*9df49d7eSJed Brown /// let qf_build_diff = ceed.q_function_interior_by_name("Poisson1DBuild").unwrap(); 1787*9df49d7eSJed Brown /// ceed.operator(&qf_build_diff, QFunctionOpt::None, QFunctionOpt::None) 1788*9df49d7eSJed Brown /// .unwrap() 1789*9df49d7eSJed Brown /// .field("dx", &rx, &bx, VectorOpt::Active) 1790*9df49d7eSJed Brown /// .unwrap() 1791*9df49d7eSJed Brown /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None) 1792*9df49d7eSJed Brown /// .unwrap() 1793*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active) 1794*9df49d7eSJed Brown /// .unwrap() 1795*9df49d7eSJed Brown /// .apply(&x, &mut qdata_diff) 1796*9df49d7eSJed Brown /// .unwrap(); 1797*9df49d7eSJed Brown /// 1798*9df49d7eSJed Brown /// // Application operator 1799*9df49d7eSJed Brown /// let qf_mass = ceed.q_function_interior_by_name("MassApply").unwrap(); 1800*9df49d7eSJed Brown /// let op_mass = ceed 1801*9df49d7eSJed Brown /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None) 1802*9df49d7eSJed Brown /// .unwrap() 1803*9df49d7eSJed Brown /// .field("u", &ru, &bu, VectorOpt::Active) 1804*9df49d7eSJed Brown /// .unwrap() 1805*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, &qdata_mass) 1806*9df49d7eSJed Brown /// .unwrap() 1807*9df49d7eSJed Brown /// .field("v", &ru, &bu, VectorOpt::Active) 1808*9df49d7eSJed Brown /// .unwrap(); 1809*9df49d7eSJed Brown /// 1810*9df49d7eSJed Brown /// let qf_diff = ceed.q_function_interior_by_name("Poisson1DApply").unwrap(); 1811*9df49d7eSJed Brown /// let op_diff = ceed 1812*9df49d7eSJed Brown /// .operator(&qf_diff, QFunctionOpt::None, QFunctionOpt::None) 1813*9df49d7eSJed Brown /// .unwrap() 1814*9df49d7eSJed Brown /// .field("du", &ru, &bu, VectorOpt::Active) 1815*9df49d7eSJed Brown /// .unwrap() 1816*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, &qdata_diff) 1817*9df49d7eSJed Brown /// .unwrap() 1818*9df49d7eSJed Brown /// .field("dv", &ru, &bu, VectorOpt::Active) 1819*9df49d7eSJed Brown /// .unwrap(); 1820*9df49d7eSJed Brown /// 1821*9df49d7eSJed Brown /// let op_composite = ceed 1822*9df49d7eSJed Brown /// .composite_operator() 1823*9df49d7eSJed Brown /// .unwrap() 1824*9df49d7eSJed Brown /// .sub_operator(&op_mass) 1825*9df49d7eSJed Brown /// .unwrap() 1826*9df49d7eSJed Brown /// .sub_operator(&op_diff) 1827*9df49d7eSJed Brown /// .unwrap(); 1828*9df49d7eSJed Brown /// 1829*9df49d7eSJed Brown /// v.set_value(0.0); 1830*9df49d7eSJed Brown /// op_composite.apply(&u, &mut v).unwrap(); 1831*9df49d7eSJed Brown /// 1832*9df49d7eSJed Brown /// // Check 1833*9df49d7eSJed Brown /// let sum: f64 = v.view().iter().sum(); 1834*9df49d7eSJed Brown /// assert!( 1835*9df49d7eSJed Brown /// (sum - 2.0).abs() < 1e-15, 1836*9df49d7eSJed Brown /// "Incorrect interval length computed" 1837*9df49d7eSJed Brown /// ); 1838*9df49d7eSJed Brown /// ``` 1839*9df49d7eSJed Brown pub fn apply(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> { 1840*9df49d7eSJed Brown self.op_core.apply(input, output) 1841*9df49d7eSJed Brown } 1842*9df49d7eSJed Brown 1843*9df49d7eSJed Brown /// Apply Operator to a vector and add result to output vector 1844*9df49d7eSJed Brown /// 1845*9df49d7eSJed Brown /// * `input` - Input Vector 1846*9df49d7eSJed Brown /// * `output` - Output Vector 1847*9df49d7eSJed Brown /// 1848*9df49d7eSJed Brown /// ``` 1849*9df49d7eSJed Brown /// # use libceed::prelude::*; 1850*9df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 1851*9df49d7eSJed Brown /// let ne = 4; 1852*9df49d7eSJed Brown /// let p = 3; 1853*9df49d7eSJed Brown /// let q = 4; 1854*9df49d7eSJed Brown /// let ndofs = p * ne - ne + 1; 1855*9df49d7eSJed Brown /// 1856*9df49d7eSJed Brown /// // Vectors 1857*9df49d7eSJed Brown /// let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0]).unwrap(); 1858*9df49d7eSJed Brown /// let mut qdata_mass = ceed.vector(ne * q).unwrap(); 1859*9df49d7eSJed Brown /// qdata_mass.set_value(0.0); 1860*9df49d7eSJed Brown /// let mut qdata_diff = ceed.vector(ne * q).unwrap(); 1861*9df49d7eSJed Brown /// qdata_diff.set_value(0.0); 1862*9df49d7eSJed Brown /// let mut u = ceed.vector(ndofs).unwrap(); 1863*9df49d7eSJed Brown /// u.set_value(1.0); 1864*9df49d7eSJed Brown /// let mut v = ceed.vector(ndofs).unwrap(); 1865*9df49d7eSJed Brown /// v.set_value(0.0); 1866*9df49d7eSJed Brown /// 1867*9df49d7eSJed Brown /// // Restrictions 1868*9df49d7eSJed Brown /// let mut indx: Vec<i32> = vec![0; 2 * ne]; 1869*9df49d7eSJed Brown /// for i in 0..ne { 1870*9df49d7eSJed Brown /// indx[2 * i + 0] = i as i32; 1871*9df49d7eSJed Brown /// indx[2 * i + 1] = (i + 1) as i32; 1872*9df49d7eSJed Brown /// } 1873*9df49d7eSJed Brown /// let rx = ceed 1874*9df49d7eSJed Brown /// .elem_restriction(ne, 2, 1, 1, ne + 1, MemType::Host, &indx) 1875*9df49d7eSJed Brown /// .unwrap(); 1876*9df49d7eSJed Brown /// let mut indu: Vec<i32> = vec![0; p * ne]; 1877*9df49d7eSJed Brown /// for i in 0..ne { 1878*9df49d7eSJed Brown /// indu[p * i + 0] = i as i32; 1879*9df49d7eSJed Brown /// indu[p * i + 1] = (i + 1) as i32; 1880*9df49d7eSJed Brown /// indu[p * i + 2] = (i + 2) as i32; 1881*9df49d7eSJed Brown /// } 1882*9df49d7eSJed Brown /// let ru = ceed 1883*9df49d7eSJed Brown /// .elem_restriction(ne, 3, 1, 1, ndofs, MemType::Host, &indu) 1884*9df49d7eSJed Brown /// .unwrap(); 1885*9df49d7eSJed Brown /// let strides: [i32; 3] = [1, q as i32, q as i32]; 1886*9df49d7eSJed Brown /// let rq = ceed 1887*9df49d7eSJed Brown /// .strided_elem_restriction(ne, q, 1, q * ne, strides) 1888*9df49d7eSJed Brown /// .unwrap(); 1889*9df49d7eSJed Brown /// 1890*9df49d7eSJed Brown /// // Bases 1891*9df49d7eSJed Brown /// let bx = ceed 1892*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss) 1893*9df49d7eSJed Brown /// .unwrap(); 1894*9df49d7eSJed Brown /// let bu = ceed 1895*9df49d7eSJed Brown /// .basis_tensor_H1_Lagrange(1, 1, p, q, QuadMode::Gauss) 1896*9df49d7eSJed Brown /// .unwrap(); 1897*9df49d7eSJed Brown /// 1898*9df49d7eSJed Brown /// // Build quadrature data 1899*9df49d7eSJed Brown /// let qf_build_mass = ceed.q_function_interior_by_name("Mass1DBuild").unwrap(); 1900*9df49d7eSJed Brown /// ceed.operator(&qf_build_mass, QFunctionOpt::None, QFunctionOpt::None) 1901*9df49d7eSJed Brown /// .unwrap() 1902*9df49d7eSJed Brown /// .field("dx", &rx, &bx, VectorOpt::Active) 1903*9df49d7eSJed Brown /// .unwrap() 1904*9df49d7eSJed Brown /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None) 1905*9df49d7eSJed Brown /// .unwrap() 1906*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active) 1907*9df49d7eSJed Brown /// .unwrap() 1908*9df49d7eSJed Brown /// .apply(&x, &mut qdata_mass) 1909*9df49d7eSJed Brown /// .unwrap(); 1910*9df49d7eSJed Brown /// 1911*9df49d7eSJed Brown /// let qf_build_diff = ceed.q_function_interior_by_name("Poisson1DBuild").unwrap(); 1912*9df49d7eSJed Brown /// ceed.operator(&qf_build_diff, QFunctionOpt::None, QFunctionOpt::None) 1913*9df49d7eSJed Brown /// .unwrap() 1914*9df49d7eSJed Brown /// .field("dx", &rx, &bx, VectorOpt::Active) 1915*9df49d7eSJed Brown /// .unwrap() 1916*9df49d7eSJed Brown /// .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None) 1917*9df49d7eSJed Brown /// .unwrap() 1918*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, VectorOpt::Active) 1919*9df49d7eSJed Brown /// .unwrap() 1920*9df49d7eSJed Brown /// .apply(&x, &mut qdata_diff) 1921*9df49d7eSJed Brown /// .unwrap(); 1922*9df49d7eSJed Brown /// 1923*9df49d7eSJed Brown /// // Application operator 1924*9df49d7eSJed Brown /// let qf_mass = ceed.q_function_interior_by_name("MassApply").unwrap(); 1925*9df49d7eSJed Brown /// let op_mass = ceed 1926*9df49d7eSJed Brown /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None) 1927*9df49d7eSJed Brown /// .unwrap() 1928*9df49d7eSJed Brown /// .field("u", &ru, &bu, VectorOpt::Active) 1929*9df49d7eSJed Brown /// .unwrap() 1930*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, &qdata_mass) 1931*9df49d7eSJed Brown /// .unwrap() 1932*9df49d7eSJed Brown /// .field("v", &ru, &bu, VectorOpt::Active) 1933*9df49d7eSJed Brown /// .unwrap(); 1934*9df49d7eSJed Brown /// 1935*9df49d7eSJed Brown /// let qf_diff = ceed.q_function_interior_by_name("Poisson1DApply").unwrap(); 1936*9df49d7eSJed Brown /// let op_diff = ceed 1937*9df49d7eSJed Brown /// .operator(&qf_diff, QFunctionOpt::None, QFunctionOpt::None) 1938*9df49d7eSJed Brown /// .unwrap() 1939*9df49d7eSJed Brown /// .field("du", &ru, &bu, VectorOpt::Active) 1940*9df49d7eSJed Brown /// .unwrap() 1941*9df49d7eSJed Brown /// .field("qdata", &rq, BasisOpt::Collocated, &qdata_diff) 1942*9df49d7eSJed Brown /// .unwrap() 1943*9df49d7eSJed Brown /// .field("dv", &ru, &bu, VectorOpt::Active) 1944*9df49d7eSJed Brown /// .unwrap(); 1945*9df49d7eSJed Brown /// 1946*9df49d7eSJed Brown /// let op_composite = ceed 1947*9df49d7eSJed Brown /// .composite_operator() 1948*9df49d7eSJed Brown /// .unwrap() 1949*9df49d7eSJed Brown /// .sub_operator(&op_mass) 1950*9df49d7eSJed Brown /// .unwrap() 1951*9df49d7eSJed Brown /// .sub_operator(&op_diff) 1952*9df49d7eSJed Brown /// .unwrap(); 1953*9df49d7eSJed Brown /// 1954*9df49d7eSJed Brown /// v.set_value(1.0); 1955*9df49d7eSJed Brown /// op_composite.apply_add(&u, &mut v).unwrap(); 1956*9df49d7eSJed Brown /// 1957*9df49d7eSJed Brown /// // Check 1958*9df49d7eSJed Brown /// let sum: f64 = v.view().iter().sum(); 1959*9df49d7eSJed Brown /// assert!( 1960*9df49d7eSJed Brown /// (sum - (2.0 + ndofs as f64)).abs() < 1e-15, 1961*9df49d7eSJed Brown /// "Incorrect interval length computed" 1962*9df49d7eSJed Brown /// ); 1963*9df49d7eSJed Brown /// ``` 1964*9df49d7eSJed Brown pub fn apply_add(&self, input: &Vector, output: &mut Vector) -> crate::Result<i32> { 1965*9df49d7eSJed Brown self.op_core.apply_add(input, output) 1966*9df49d7eSJed Brown } 1967*9df49d7eSJed Brown 1968*9df49d7eSJed Brown /// Add a sub-Operator to a Composite Operator 1969*9df49d7eSJed Brown /// 1970*9df49d7eSJed Brown /// * `subop` - Sub-Operator 1971*9df49d7eSJed Brown /// 1972*9df49d7eSJed Brown /// ``` 1973*9df49d7eSJed Brown /// # use libceed::prelude::*; 1974*9df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 1975*9df49d7eSJed Brown /// let mut op = ceed.composite_operator().unwrap(); 1976*9df49d7eSJed Brown /// 1977*9df49d7eSJed Brown /// let qf_mass = ceed.q_function_interior_by_name("MassApply").unwrap(); 1978*9df49d7eSJed Brown /// let op_mass = ceed 1979*9df49d7eSJed Brown /// .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None) 1980*9df49d7eSJed Brown /// .unwrap(); 1981*9df49d7eSJed Brown /// op = op.sub_operator(&op_mass).unwrap(); 1982*9df49d7eSJed Brown /// 1983*9df49d7eSJed Brown /// let qf_diff = ceed.q_function_interior_by_name("Poisson1DApply").unwrap(); 1984*9df49d7eSJed Brown /// let op_diff = ceed 1985*9df49d7eSJed Brown /// .operator(&qf_diff, QFunctionOpt::None, QFunctionOpt::None) 1986*9df49d7eSJed Brown /// .unwrap(); 1987*9df49d7eSJed Brown /// op = op.sub_operator(&op_diff).unwrap(); 1988*9df49d7eSJed Brown /// ``` 1989*9df49d7eSJed Brown #[allow(unused_mut)] 1990*9df49d7eSJed Brown pub fn sub_operator(mut self, subop: &Operator) -> crate::Result<Self> { 1991*9df49d7eSJed Brown let ierr = 1992*9df49d7eSJed Brown unsafe { bind_ceed::CeedCompositeOperatorAddSub(self.op_core.ptr, subop.op_core.ptr) }; 1993*9df49d7eSJed Brown self.op_core.ceed.check_error(ierr)?; 1994*9df49d7eSJed Brown Ok(self) 1995*9df49d7eSJed Brown } 1996*9df49d7eSJed Brown 1997*9df49d7eSJed Brown /// Assemble the diagonal of a square linear Operator 1998*9df49d7eSJed Brown /// 1999*9df49d7eSJed Brown /// This overwrites a Vector with the diagonal of a linear Operator. 2000*9df49d7eSJed Brown /// 2001*9df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 2002*9df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 2003*9df49d7eSJed Brown /// 2004*9df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 2005*9df49d7eSJed Brown /// * `assembled` - Vector to store assembled Operator diagonal 2006*9df49d7eSJed Brown pub fn linear_asssemble_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> { 2007*9df49d7eSJed Brown self.op_core.linear_assemble_add_diagonal(assembled) 2008*9df49d7eSJed Brown } 2009*9df49d7eSJed Brown 2010*9df49d7eSJed Brown /// Assemble the point block diagonal of a square linear Operator 2011*9df49d7eSJed Brown /// 2012*9df49d7eSJed Brown /// This overwrites a Vector with the point block diagonal of a linear 2013*9df49d7eSJed Brown /// Operator. 2014*9df49d7eSJed Brown /// 2015*9df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 2016*9df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 2017*9df49d7eSJed Brown /// 2018*9df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 2019*9df49d7eSJed Brown /// * `assembled` - Vector to store assembled Operator diagonal 2020*9df49d7eSJed Brown pub fn linear_assemble_add_diagonal(&self, assembled: &mut Vector) -> crate::Result<i32> { 2021*9df49d7eSJed Brown self.op_core.linear_assemble_add_diagonal(assembled) 2022*9df49d7eSJed Brown } 2023*9df49d7eSJed Brown 2024*9df49d7eSJed Brown /// Assemble the diagonal of a square linear Operator 2025*9df49d7eSJed Brown /// 2026*9df49d7eSJed Brown /// This overwrites a Vector with the diagonal of a linear Operator. 2027*9df49d7eSJed Brown /// 2028*9df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 2029*9df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 2030*9df49d7eSJed Brown /// 2031*9df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 2032*9df49d7eSJed Brown /// * `assembled` - Vector to store assembled CeedOperator point block 2033*9df49d7eSJed Brown /// diagonal, provided in row-major form with an 2034*9df49d7eSJed Brown /// `ncomp * ncomp` block at each node. The dimensions of 2035*9df49d7eSJed Brown /// this vector are derived from the active vector for 2036*9df49d7eSJed Brown /// the CeedOperator. The array has shape 2037*9df49d7eSJed Brown /// `[nodes, component out, component in]`. 2038*9df49d7eSJed Brown pub fn linear_assemble_point_block_diagonal( 2039*9df49d7eSJed Brown &self, 2040*9df49d7eSJed Brown assembled: &mut Vector, 2041*9df49d7eSJed Brown ) -> crate::Result<i32> { 2042*9df49d7eSJed Brown self.op_core.linear_assemble_add_diagonal(assembled) 2043*9df49d7eSJed Brown } 2044*9df49d7eSJed Brown 2045*9df49d7eSJed Brown /// Assemble the diagonal of a square linear Operator 2046*9df49d7eSJed Brown /// 2047*9df49d7eSJed Brown /// This sums into a Vector with the diagonal of a linear Operator. 2048*9df49d7eSJed Brown /// 2049*9df49d7eSJed Brown /// Note: Currently only non-composite Operators with a single field and 2050*9df49d7eSJed Brown /// composite Operators with single field sub-operators are supported. 2051*9df49d7eSJed Brown /// 2052*9df49d7eSJed Brown /// * `op` - Operator to assemble QFunction 2053*9df49d7eSJed Brown /// * `assembled` - Vector to store assembled CeedOperator point block 2054*9df49d7eSJed Brown /// diagonal, provided in row-major form with an 2055*9df49d7eSJed Brown /// `ncomp * ncomp` block at each node. The dimensions of 2056*9df49d7eSJed Brown /// this vector are derived from the active vector for 2057*9df49d7eSJed Brown /// the CeedOperator. The array has shape 2058*9df49d7eSJed Brown /// `[nodes, component out, component in]`. 2059*9df49d7eSJed Brown pub fn linear_assemble_add_point_block_diagonal( 2060*9df49d7eSJed Brown &self, 2061*9df49d7eSJed Brown assembled: &mut Vector, 2062*9df49d7eSJed Brown ) -> crate::Result<i32> { 2063*9df49d7eSJed Brown self.op_core.linear_assemble_add_diagonal(assembled) 2064*9df49d7eSJed Brown } 2065*9df49d7eSJed Brown } 2066*9df49d7eSJed Brown 2067*9df49d7eSJed Brown // ----------------------------------------------------------------------------- 2068