1d275d636SJeremy L Thompson // Copyright (c) 2017-2025, Lawrence Livermore National Security, LLC and other CEED contributors. 23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 39df49d7eSJed Brown // 43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 59df49d7eSJed Brown // 63d8e8822SJeremy L Thompson // This file is part of CEED: http://github.com/ceed 79df49d7eSJed Brown 8a1cbad85SJed Brown // Fenced `rust` code blocks included from README.md are executed as part of doctests. 9a1cbad85SJed Brown #![doc = include_str!("../README.md")] 109df49d7eSJed Brown // ----------------------------------------------------------------------------- 119df49d7eSJed Brown // Exceptions 129df49d7eSJed Brown // ----------------------------------------------------------------------------- 139df49d7eSJed Brown #![allow(non_snake_case)] 149df49d7eSJed Brown 159df49d7eSJed Brown // ----------------------------------------------------------------------------- 169df49d7eSJed Brown // Crate prelude 179df49d7eSJed Brown // ----------------------------------------------------------------------------- 189df49d7eSJed Brown use crate::prelude::*; 199df49d7eSJed Brown use std::sync::Once; 209df49d7eSJed Brown 219df49d7eSJed Brown pub mod prelude { 22630ad4c9Sjeremylt pub(crate) use libceed_sys::bind_ceed; 239df49d7eSJed Brown pub(crate) use std::convert::TryFrom; 2408778c6fSJeremy L Thompson pub(crate) use std::ffi::{CStr, CString}; 259df49d7eSJed Brown pub(crate) use std::fmt; 261142270cSJeremy L Thompson pub(crate) use std::marker::PhantomData; 279df49d7eSJed Brown } 289df49d7eSJed Brown 299df49d7eSJed Brown // ----------------------------------------------------------------------------- 309df49d7eSJed Brown // Modules 319df49d7eSJed Brown // ----------------------------------------------------------------------------- 329df49d7eSJed Brown pub mod basis; 339df49d7eSJed Brown pub mod elem_restriction; 349df49d7eSJed Brown pub mod operator; 359df49d7eSJed Brown pub mod qfunction; 369df49d7eSJed Brown pub mod vector; 379df49d7eSJed Brown 389df49d7eSJed Brown // ----------------------------------------------------------------------------- 3980a9ef05SNatalie Beams // Typedef for scalar 4080a9ef05SNatalie Beams // ----------------------------------------------------------------------------- 4180a9ef05SNatalie Beams pub type Scalar = bind_ceed::CeedScalar; 4280a9ef05SNatalie Beams 4380a9ef05SNatalie Beams // ----------------------------------------------------------------------------- 449df49d7eSJed Brown // Constants for library 459df49d7eSJed Brown // ----------------------------------------------------------------------------- 46257916f8SJed Brown const MAX_BUFFER_LENGTH: usize = 4096; 479df49d7eSJed Brown pub const MAX_QFUNCTION_FIELDS: usize = 16; 489df49d7eSJed Brown pub const CEED_STRIDES_BACKEND: [i32; 3] = [0; 3]; 4980a9ef05SNatalie Beams pub const EPSILON: crate::Scalar = bind_ceed::CEED_EPSILON as crate::Scalar; 509df49d7eSJed Brown 519df49d7eSJed Brown // ----------------------------------------------------------------------------- 529df49d7eSJed Brown // Enums for libCEED 539df49d7eSJed Brown // ----------------------------------------------------------------------------- 549df49d7eSJed Brown #[derive(Clone, Copy, PartialEq, Eq)] 559df49d7eSJed Brown /// Many Ceed interfaces take or return pointers to memory. This enum is used to 569df49d7eSJed Brown /// specify where the memory being provided or requested must reside. 579df49d7eSJed Brown pub enum MemType { 589df49d7eSJed Brown Host = bind_ceed::CeedMemType_CEED_MEM_HOST as isize, 599df49d7eSJed Brown Device = bind_ceed::CeedMemType_CEED_MEM_DEVICE as isize, 609df49d7eSJed Brown } 619df49d7eSJed Brown 629df49d7eSJed Brown #[derive(Clone, Copy, PartialEq, Eq)] 639df49d7eSJed Brown // OwnPointer will not be used by user but is included for internal use 649df49d7eSJed Brown #[allow(dead_code)] 659df49d7eSJed Brown /// Conveys ownership status of arrays passed to Ceed interfaces. 669df49d7eSJed Brown pub(crate) enum CopyMode { 679df49d7eSJed Brown CopyValues = bind_ceed::CeedCopyMode_CEED_COPY_VALUES as isize, 689df49d7eSJed Brown UsePointer = bind_ceed::CeedCopyMode_CEED_USE_POINTER as isize, 699df49d7eSJed Brown OwnPointer = bind_ceed::CeedCopyMode_CEED_OWN_POINTER as isize, 709df49d7eSJed Brown } 719df49d7eSJed Brown 729df49d7eSJed Brown #[derive(Clone, Copy, PartialEq, Eq)] 739df49d7eSJed Brown /// Denotes type of vector norm to be computed 749df49d7eSJed Brown pub enum NormType { 759df49d7eSJed Brown One = bind_ceed::CeedNormType_CEED_NORM_1 as isize, 769df49d7eSJed Brown Two = bind_ceed::CeedNormType_CEED_NORM_2 as isize, 779df49d7eSJed Brown Max = bind_ceed::CeedNormType_CEED_NORM_MAX as isize, 789df49d7eSJed Brown } 799df49d7eSJed Brown 809df49d7eSJed Brown #[derive(Clone, Copy, PartialEq, Eq)] 819df49d7eSJed Brown /// Denotes whether a linear transformation or its transpose should be applied 829df49d7eSJed Brown pub enum TransposeMode { 839df49d7eSJed Brown NoTranspose = bind_ceed::CeedTransposeMode_CEED_NOTRANSPOSE as isize, 849df49d7eSJed Brown Transpose = bind_ceed::CeedTransposeMode_CEED_TRANSPOSE as isize, 859df49d7eSJed Brown } 869df49d7eSJed Brown 879df49d7eSJed Brown #[derive(Clone, Copy, PartialEq, Eq)] 889df49d7eSJed Brown /// Type of quadrature; also used for location of nodes 899df49d7eSJed Brown pub enum QuadMode { 909df49d7eSJed Brown Gauss = bind_ceed::CeedQuadMode_CEED_GAUSS as isize, 919df49d7eSJed Brown GaussLobatto = bind_ceed::CeedQuadMode_CEED_GAUSS_LOBATTO as isize, 929df49d7eSJed Brown } 939df49d7eSJed Brown 949df49d7eSJed Brown #[derive(Clone, Copy, PartialEq, Eq)] 959df49d7eSJed Brown /// Type of basis shape to create non-tensor H1 element basis 969df49d7eSJed Brown pub enum ElemTopology { 9750c301a5SRezgar Shakeri Line = bind_ceed::CeedElemTopology_CEED_TOPOLOGY_LINE as isize, 9850c301a5SRezgar Shakeri Triangle = bind_ceed::CeedElemTopology_CEED_TOPOLOGY_TRIANGLE as isize, 9950c301a5SRezgar Shakeri Quad = bind_ceed::CeedElemTopology_CEED_TOPOLOGY_QUAD as isize, 10050c301a5SRezgar Shakeri Tet = bind_ceed::CeedElemTopology_CEED_TOPOLOGY_TET as isize, 10150c301a5SRezgar Shakeri Pyramid = bind_ceed::CeedElemTopology_CEED_TOPOLOGY_PYRAMID as isize, 10250c301a5SRezgar Shakeri Prism = bind_ceed::CeedElemTopology_CEED_TOPOLOGY_PRISM as isize, 10350c301a5SRezgar Shakeri Hex = bind_ceed::CeedElemTopology_CEED_TOPOLOGY_HEX as isize, 1049df49d7eSJed Brown } 1059df49d7eSJed Brown 106c68be7a2SJeremy L Thompson #[derive(Clone, Copy, Debug, PartialEq, Eq)] 1079df49d7eSJed Brown /// Basis evaluation mode 1089df49d7eSJed Brown pub enum EvalMode { 1099df49d7eSJed Brown None = bind_ceed::CeedEvalMode_CEED_EVAL_NONE as isize, 1109df49d7eSJed Brown Interp = bind_ceed::CeedEvalMode_CEED_EVAL_INTERP as isize, 1119df49d7eSJed Brown Grad = bind_ceed::CeedEvalMode_CEED_EVAL_GRAD as isize, 1129df49d7eSJed Brown Div = bind_ceed::CeedEvalMode_CEED_EVAL_DIV as isize, 1139df49d7eSJed Brown Curl = bind_ceed::CeedEvalMode_CEED_EVAL_CURL as isize, 1149df49d7eSJed Brown Weight = bind_ceed::CeedEvalMode_CEED_EVAL_WEIGHT as isize, 1159df49d7eSJed Brown } 116c68be7a2SJeremy L Thompson impl EvalMode { 117c68be7a2SJeremy L Thompson pub(crate) fn from_u32(value: u32) -> EvalMode { 118c68be7a2SJeremy L Thompson match value { 119c68be7a2SJeremy L Thompson bind_ceed::CeedEvalMode_CEED_EVAL_NONE => EvalMode::None, 120c68be7a2SJeremy L Thompson bind_ceed::CeedEvalMode_CEED_EVAL_INTERP => EvalMode::Interp, 121c68be7a2SJeremy L Thompson bind_ceed::CeedEvalMode_CEED_EVAL_GRAD => EvalMode::Grad, 122c68be7a2SJeremy L Thompson bind_ceed::CeedEvalMode_CEED_EVAL_DIV => EvalMode::Div, 123c68be7a2SJeremy L Thompson bind_ceed::CeedEvalMode_CEED_EVAL_CURL => EvalMode::Curl, 124c68be7a2SJeremy L Thompson bind_ceed::CeedEvalMode_CEED_EVAL_WEIGHT => EvalMode::Weight, 125c68be7a2SJeremy L Thompson _ => panic!("Unknown value: {}", value), 126c68be7a2SJeremy L Thompson } 127c68be7a2SJeremy L Thompson } 128c68be7a2SJeremy L Thompson } 1299df49d7eSJed Brown 1309df49d7eSJed Brown // ----------------------------------------------------------------------------- 1319df49d7eSJed Brown // Ceed error 1329df49d7eSJed Brown // ----------------------------------------------------------------------------- 1332ba8e59cSJeremy L Thompson pub type Result<T> = std::result::Result<T, Error>; 1349df49d7eSJed Brown 1357ed177dbSJed Brown /// libCEED error messages - returning an Error without painc!ing indicates 1367ed177dbSJed Brown /// the function call failed but the data is not corrupted 1379df49d7eSJed Brown #[derive(Debug)] 1382ba8e59cSJeremy L Thompson pub struct Error { 1399df49d7eSJed Brown pub message: String, 1409df49d7eSJed Brown } 1419df49d7eSJed Brown 1422ba8e59cSJeremy L Thompson impl fmt::Display for Error { 1439df49d7eSJed Brown fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 1449df49d7eSJed Brown write!(f, "{}", self.message) 1459df49d7eSJed Brown } 1469df49d7eSJed Brown } 1479df49d7eSJed Brown 1489df49d7eSJed Brown // ----------------------------------------------------------------------------- 149eb07d68fSJeremy L Thompson // Internal crate contents 150eb07d68fSJeremy L Thompson // ----------------------------------------------------------------------------- 151eb07d68fSJeremy L Thompson pub use crate::{ 152eb07d68fSJeremy L Thompson basis::{Basis, BasisOpt}, 153eb07d68fSJeremy L Thompson elem_restriction::{ElemRestriction, ElemRestrictionOpt}, 154eb07d68fSJeremy L Thompson operator::{CompositeOperator, Operator, OperatorField}, 155eb07d68fSJeremy L Thompson qfunction::{ 156eb07d68fSJeremy L Thompson QFunction, QFunctionByName, QFunctionField, QFunctionInputs, QFunctionOpt, QFunctionOutputs, 157eb07d68fSJeremy L Thompson }, 158eb07d68fSJeremy L Thompson vector::{Vector, VectorOpt, VectorSliceWrapper}, 159eb07d68fSJeremy L Thompson }; 160eb07d68fSJeremy L Thompson 161eb07d68fSJeremy L Thompson // ----------------------------------------------------------------------------- 1621142270cSJeremy L Thompson // Internal error checker 1631142270cSJeremy L Thompson // ----------------------------------------------------------------------------- 1641142270cSJeremy L Thompson #[doc(hidden)] 16511544396SJeremy L Thompson pub(crate) fn check_error<F>(ceed_ptr: F, ierr: i32) -> Result<i32> 16611544396SJeremy L Thompson where 16711544396SJeremy L Thompson F: FnOnce() -> bind_ceed::Ceed, 16811544396SJeremy L Thompson { 1691142270cSJeremy L Thompson // Return early if code is clean 1701142270cSJeremy L Thompson if ierr == bind_ceed::CeedErrorType_CEED_ERROR_SUCCESS { 1711142270cSJeremy L Thompson return Ok(ierr); 1721142270cSJeremy L Thompson } 1731142270cSJeremy L Thompson // Retrieve error message 1741142270cSJeremy L Thompson let mut ptr: *const std::os::raw::c_char = std::ptr::null_mut(); 1751142270cSJeremy L Thompson let c_str = unsafe { 17611544396SJeremy L Thompson bind_ceed::CeedGetErrorMessage(ceed_ptr(), &mut ptr); 1771142270cSJeremy L Thompson std::ffi::CStr::from_ptr(ptr) 1781142270cSJeremy L Thompson }; 1791142270cSJeremy L Thompson let message = c_str.to_string_lossy().to_string(); 1801142270cSJeremy L Thompson // Panic if negative code, otherwise return error 1811142270cSJeremy L Thompson if ierr < bind_ceed::CeedErrorType_CEED_ERROR_SUCCESS { 1821142270cSJeremy L Thompson panic!("{}", message); 1831142270cSJeremy L Thompson } 1842ba8e59cSJeremy L Thompson Err(Error { message }) 1851142270cSJeremy L Thompson } 1861142270cSJeremy L Thompson 1871142270cSJeremy L Thompson // ----------------------------------------------------------------------------- 1889df49d7eSJed Brown // Ceed error handler 1899df49d7eSJed Brown // ----------------------------------------------------------------------------- 1902ba8e59cSJeremy L Thompson pub enum ErrorHandler { 1919df49d7eSJed Brown ErrorAbort, 1929df49d7eSJed Brown ErrorExit, 1939df49d7eSJed Brown ErrorReturn, 1949df49d7eSJed Brown ErrorStore, 1959df49d7eSJed Brown } 1969df49d7eSJed Brown 1979df49d7eSJed Brown // ----------------------------------------------------------------------------- 1989df49d7eSJed Brown // Ceed context wrapper 1999df49d7eSJed Brown // ----------------------------------------------------------------------------- 2009df49d7eSJed Brown /// A Ceed is a library context representing control of a logical hardware 2019df49d7eSJed Brown /// resource. 2029df49d7eSJed Brown #[derive(Debug)] 2039df49d7eSJed Brown pub struct Ceed { 2049df49d7eSJed Brown ptr: bind_ceed::Ceed, 2059df49d7eSJed Brown } 2069df49d7eSJed Brown 2079df49d7eSJed Brown // ----------------------------------------------------------------------------- 2089df49d7eSJed Brown // Destructor 2099df49d7eSJed Brown // ----------------------------------------------------------------------------- 2109df49d7eSJed Brown impl Drop for Ceed { 2119df49d7eSJed Brown fn drop(&mut self) { 2129df49d7eSJed Brown unsafe { 2139df49d7eSJed Brown bind_ceed::CeedDestroy(&mut self.ptr); 2149df49d7eSJed Brown } 2159df49d7eSJed Brown } 2169df49d7eSJed Brown } 2179df49d7eSJed Brown 2189df49d7eSJed Brown // ----------------------------------------------------------------------------- 21959189cfaSJeremy L Thompson // Cloning 22059189cfaSJeremy L Thompson // ----------------------------------------------------------------------------- 22159189cfaSJeremy L Thompson impl Clone for Ceed { 22259189cfaSJeremy L Thompson /// Perform a shallow clone of a Ceed context 22359189cfaSJeremy L Thompson /// 22459189cfaSJeremy L Thompson /// ``` 22559189cfaSJeremy L Thompson /// let ceed = libceed::Ceed::init("/cpu/self/ref/serial"); 22659189cfaSJeremy L Thompson /// let ceed_clone = ceed.clone(); 22759189cfaSJeremy L Thompson /// 2287ed177dbSJed Brown /// println!(" original:{} \n clone:{}", ceed, ceed_clone); 22959189cfaSJeremy L Thompson /// ``` 23059189cfaSJeremy L Thompson fn clone(&self) -> Self { 23159189cfaSJeremy L Thompson let mut ptr_clone = std::ptr::null_mut(); 232656ef1e5SJeremy L Thompson self.check_error(unsafe { bind_ceed::CeedReferenceCopy(self.ptr, &mut ptr_clone) }) 233656ef1e5SJeremy L Thompson .expect("failed to clone Ceed"); 23459189cfaSJeremy L Thompson Self { ptr: ptr_clone } 23559189cfaSJeremy L Thompson } 23659189cfaSJeremy L Thompson } 23759189cfaSJeremy L Thompson 23859189cfaSJeremy L Thompson // ----------------------------------------------------------------------------- 2399df49d7eSJed Brown // Display 2409df49d7eSJed Brown // ----------------------------------------------------------------------------- 2419df49d7eSJed Brown impl fmt::Display for Ceed { 2429df49d7eSJed Brown /// View a Ceed 2439df49d7eSJed Brown /// 2449df49d7eSJed Brown /// ``` 2459df49d7eSJed Brown /// let ceed = libceed::Ceed::init("/cpu/self/ref/serial"); 2469df49d7eSJed Brown /// println!("{}", ceed); 2479df49d7eSJed Brown /// ``` 2489df49d7eSJed Brown fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 2499df49d7eSJed Brown let mut ptr = std::ptr::null_mut(); 2509df49d7eSJed Brown let mut sizeloc = crate::MAX_BUFFER_LENGTH; 2519df49d7eSJed Brown let cstring = unsafe { 2529df49d7eSJed Brown let file = bind_ceed::open_memstream(&mut ptr, &mut sizeloc); 2539df49d7eSJed Brown bind_ceed::CeedView(self.ptr, file); 2549df49d7eSJed Brown bind_ceed::fclose(file); 2559df49d7eSJed Brown CString::from_raw(ptr) 2569df49d7eSJed Brown }; 2579df49d7eSJed Brown cstring.to_string_lossy().fmt(f) 2589df49d7eSJed Brown } 2599df49d7eSJed Brown } 2609df49d7eSJed Brown 2619df49d7eSJed Brown static REGISTER: Once = Once::new(); 2629df49d7eSJed Brown 2639df49d7eSJed Brown // ----------------------------------------------------------------------------- 2649df49d7eSJed Brown // Object constructors 2659df49d7eSJed Brown // ----------------------------------------------------------------------------- 2669df49d7eSJed Brown impl Ceed { 2677ed177dbSJed Brown #[cfg_attr(feature = "katexit", katexit::katexit)] 2689df49d7eSJed Brown /// Returns a Ceed context initialized with the specified resource 2699df49d7eSJed Brown /// 2709df49d7eSJed Brown /// # arguments 2719df49d7eSJed Brown /// 2729df49d7eSJed Brown /// * `resource` - Resource to use, e.g., "/cpu/self" 2739df49d7eSJed Brown /// 2749df49d7eSJed Brown /// ``` 2759df49d7eSJed Brown /// let ceed = libceed::Ceed::init("/cpu/self/ref/serial"); 2769df49d7eSJed Brown /// ``` 2779df49d7eSJed Brown pub fn init(resource: &str) -> Self { 2782ba8e59cSJeremy L Thompson Ceed::init_with_error_handler(resource, ErrorHandler::ErrorStore) 2799df49d7eSJed Brown } 2809df49d7eSJed Brown 2819df49d7eSJed Brown /// Returns a Ceed context initialized with the specified resource 2829df49d7eSJed Brown /// 2839df49d7eSJed Brown /// # arguments 2849df49d7eSJed Brown /// 2859df49d7eSJed Brown /// * `resource` - Resource to use, e.g., "/cpu/self" 2869df49d7eSJed Brown /// 2879df49d7eSJed Brown /// ``` 2889df49d7eSJed Brown /// let ceed = libceed::Ceed::init_with_error_handler( 2899df49d7eSJed Brown /// "/cpu/self/ref/serial", 2902ba8e59cSJeremy L Thompson /// libceed::ErrorHandler::ErrorAbort, 2919df49d7eSJed Brown /// ); 2929df49d7eSJed Brown /// ``` 2932ba8e59cSJeremy L Thompson pub fn init_with_error_handler(resource: &str, handler: ErrorHandler) -> Self { 2949df49d7eSJed Brown REGISTER.call_once(|| unsafe { 2959df49d7eSJed Brown bind_ceed::CeedRegisterAll(); 2969df49d7eSJed Brown bind_ceed::CeedQFunctionRegisterAll(); 2979df49d7eSJed Brown }); 2989df49d7eSJed Brown 2999df49d7eSJed Brown // Convert to C string 3009df49d7eSJed Brown let c_resource = CString::new(resource).expect("CString::new failed"); 3019df49d7eSJed Brown 3029df49d7eSJed Brown // Get error handler pointer 3039df49d7eSJed Brown let eh = match handler { 3042ba8e59cSJeremy L Thompson ErrorHandler::ErrorAbort => bind_ceed::CeedErrorAbort, 3052ba8e59cSJeremy L Thompson ErrorHandler::ErrorExit => bind_ceed::CeedErrorExit, 3062ba8e59cSJeremy L Thompson ErrorHandler::ErrorReturn => bind_ceed::CeedErrorReturn, 3072ba8e59cSJeremy L Thompson ErrorHandler::ErrorStore => bind_ceed::CeedErrorStore, 3089df49d7eSJed Brown }; 3099df49d7eSJed Brown 3109df49d7eSJed Brown // Call to libCEED 3119df49d7eSJed Brown let mut ptr = std::ptr::null_mut(); 312bf55b007SJeremy L Thompson let mut ierr = unsafe { bind_ceed::CeedInit(c_resource.as_ptr(), &mut ptr) }; 3139df49d7eSJed Brown if ierr != 0 { 3149df49d7eSJed Brown panic!("Error initializing backend resource: {}", resource) 3159df49d7eSJed Brown } 3169df49d7eSJed Brown ierr = unsafe { bind_ceed::CeedSetErrorHandler(ptr, Some(eh)) }; 3179df49d7eSJed Brown let ceed = Ceed { ptr }; 3189df49d7eSJed Brown ceed.check_error(ierr).unwrap(); 3199df49d7eSJed Brown ceed 3209df49d7eSJed Brown } 3219df49d7eSJed Brown 3229df49d7eSJed Brown /// Default initializer for testing 3239df49d7eSJed Brown #[doc(hidden)] 3249df49d7eSJed Brown pub fn default_init() -> Self { 3259df49d7eSJed Brown // Convert to C string 3269df49d7eSJed Brown let resource = "/cpu/self/ref/serial"; 3279df49d7eSJed Brown crate::Ceed::init(resource) 3289df49d7eSJed Brown } 3299df49d7eSJed Brown 3309df49d7eSJed Brown /// Internal error checker 3319df49d7eSJed Brown #[doc(hidden)] 3329df49d7eSJed Brown fn check_error(&self, ierr: i32) -> Result<i32> { 3339df49d7eSJed Brown // Return early if code is clean 3349df49d7eSJed Brown if ierr == bind_ceed::CeedErrorType_CEED_ERROR_SUCCESS { 3359df49d7eSJed Brown return Ok(ierr); 3369df49d7eSJed Brown } 3379df49d7eSJed Brown // Retrieve error message 3389df49d7eSJed Brown let mut ptr: *const std::os::raw::c_char = std::ptr::null_mut(); 3399df49d7eSJed Brown let c_str = unsafe { 3409df49d7eSJed Brown bind_ceed::CeedGetErrorMessage(self.ptr, &mut ptr); 3419df49d7eSJed Brown std::ffi::CStr::from_ptr(ptr) 3429df49d7eSJed Brown }; 3439df49d7eSJed Brown let message = c_str.to_string_lossy().to_string(); 3449df49d7eSJed Brown // Panic if negative code, otherwise return error 3459df49d7eSJed Brown if ierr < bind_ceed::CeedErrorType_CEED_ERROR_SUCCESS { 3469df49d7eSJed Brown panic!("{}", message); 3479df49d7eSJed Brown } 3482ba8e59cSJeremy L Thompson Err(Error { message }) 3499df49d7eSJed Brown } 3509df49d7eSJed Brown 3519df49d7eSJed Brown /// Returns full resource name for a Ceed context 3529df49d7eSJed Brown /// 3539df49d7eSJed Brown /// ``` 3549df49d7eSJed Brown /// let ceed = libceed::Ceed::init("/cpu/self/ref/serial"); 3559df49d7eSJed Brown /// let resource = ceed.resource(); 3569df49d7eSJed Brown /// 3579df49d7eSJed Brown /// assert_eq!(resource, "/cpu/self/ref/serial".to_string()) 3589df49d7eSJed Brown /// ``` 3599df49d7eSJed Brown pub fn resource(&self) -> String { 3609df49d7eSJed Brown let mut ptr: *const std::os::raw::c_char = std::ptr::null_mut(); 3619df49d7eSJed Brown let c_str = unsafe { 3629df49d7eSJed Brown bind_ceed::CeedGetResource(self.ptr, &mut ptr); 3639df49d7eSJed Brown std::ffi::CStr::from_ptr(ptr) 3649df49d7eSJed Brown }; 3659df49d7eSJed Brown c_str.to_string_lossy().to_string() 3669df49d7eSJed Brown } 3679df49d7eSJed Brown 3687ed177dbSJed Brown /// Returns a Vector of the specified length (does not allocate memory) 3699df49d7eSJed Brown /// 3709df49d7eSJed Brown /// # arguments 3719df49d7eSJed Brown /// 3729df49d7eSJed Brown /// * `n` - Length of vector 3739df49d7eSJed Brown /// 3749df49d7eSJed Brown /// ``` 3759df49d7eSJed Brown /// # use libceed::prelude::*; 3764d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 3779df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 378c68be7a2SJeremy L Thompson /// let vec = ceed.vector(10)?; 379c68be7a2SJeremy L Thompson /// # Ok(()) 380c68be7a2SJeremy L Thompson /// # } 3819df49d7eSJed Brown /// ``` 382594ef120SJeremy L Thompson pub fn vector<'a>(&self, n: usize) -> Result<Vector<'a>> { 3839df49d7eSJed Brown Vector::create(self, n) 3849df49d7eSJed Brown } 3859df49d7eSJed Brown 3869df49d7eSJed Brown /// Create a Vector initialized with the data (copied) from a slice 3879df49d7eSJed Brown /// 3889df49d7eSJed Brown /// # arguments 3899df49d7eSJed Brown /// 3909df49d7eSJed Brown /// * `slice` - Slice containing data 3919df49d7eSJed Brown /// 3929df49d7eSJed Brown /// ``` 3939df49d7eSJed Brown /// # use libceed::prelude::*; 3944d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 3959df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 396c68be7a2SJeremy L Thompson /// let vec = ceed.vector_from_slice(&[1., 2., 3.])?; 3979df49d7eSJed Brown /// assert_eq!(vec.length(), 3); 398c68be7a2SJeremy L Thompson /// # Ok(()) 399c68be7a2SJeremy L Thompson /// # } 4009df49d7eSJed Brown /// ``` 401594ef120SJeremy L Thompson pub fn vector_from_slice<'a>(&self, slice: &[crate::Scalar]) -> Result<Vector<'a>> { 4029df49d7eSJed Brown Vector::from_slice(self, slice) 4039df49d7eSJed Brown } 4049df49d7eSJed Brown 4057ed177dbSJed Brown /// Returns an ElemRestriction, $\mathcal{E}$, which extracts the degrees of 4067ed177dbSJed Brown /// freedom for each element from the local vector into the element vector 4077ed177dbSJed Brown /// or assembles contributions from each element in the element vector to 4087ed177dbSJed Brown /// the local vector 4099df49d7eSJed Brown /// 4109df49d7eSJed Brown /// # arguments 4119df49d7eSJed Brown /// 4129df49d7eSJed Brown /// * `nelem` - Number of elements described in the offsets array 4139df49d7eSJed Brown /// * `elemsize` - Size (number of "nodes") per element 4149df49d7eSJed Brown /// * `ncomp` - Number of field components per interpolation node (1 4159df49d7eSJed Brown /// for scalar fields) 4169df49d7eSJed Brown /// * `compstride` - Stride between components for the same Lvector "node". 4179df49d7eSJed Brown /// Data for node `i`, component `j`, element `k` can be 4189df49d7eSJed Brown /// found in the Lvector at index 4199df49d7eSJed Brown /// `offsets[i + k*elemsize] + j*compstride`. 4209df49d7eSJed Brown /// * `lsize` - The size of the Lvector. This vector may be larger 4219df49d7eSJed Brown /// than the elements and fields given by this 4229df49d7eSJed Brown /// restriction. 4239df49d7eSJed Brown /// * `mtype` - Memory type of the offsets array, see CeedMemType 4249df49d7eSJed Brown /// * `offsets` - Array of shape `[nelem, elemsize]`. Row `i` holds the 4259df49d7eSJed Brown /// ordered list of the offsets (into the input CeedVector) 4269df49d7eSJed Brown /// for the unknowns corresponding to element `i`, where 4279df49d7eSJed Brown /// `0 <= i < nelem`. All offsets must be in the range 4289df49d7eSJed Brown /// `[0, lsize - 1]`. 4299df49d7eSJed Brown /// 4309df49d7eSJed Brown /// ``` 431eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, MemType}; 4324d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 4339df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 4349df49d7eSJed Brown /// let nelem = 3; 4359df49d7eSJed Brown /// let mut ind: Vec<i32> = vec![0; 2 * nelem]; 4369df49d7eSJed Brown /// for i in 0..nelem { 4379df49d7eSJed Brown /// ind[2 * i + 0] = i as i32; 4389df49d7eSJed Brown /// ind[2 * i + 1] = (i + 1) as i32; 4399df49d7eSJed Brown /// } 440c68be7a2SJeremy L Thompson /// let r = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind)?; 441c68be7a2SJeremy L Thompson /// # Ok(()) 442c68be7a2SJeremy L Thompson /// # } 4439df49d7eSJed Brown /// ``` 444*78c2cefaSJeremy L Thompson #[allow(clippy::too_many_arguments)] 445594ef120SJeremy L Thompson pub fn elem_restriction<'a>( 4469df49d7eSJed Brown &self, 4479df49d7eSJed Brown nelem: usize, 4489df49d7eSJed Brown elemsize: usize, 4499df49d7eSJed Brown ncomp: usize, 4509df49d7eSJed Brown compstride: usize, 4519df49d7eSJed Brown lsize: usize, 4529df49d7eSJed Brown mtype: MemType, 4539df49d7eSJed Brown offsets: &[i32], 454594ef120SJeremy L Thompson ) -> Result<ElemRestriction<'a>> { 4559df49d7eSJed Brown ElemRestriction::create( 4569df49d7eSJed Brown self, nelem, elemsize, ncomp, compstride, lsize, mtype, offsets, 457709403c1SSebastian Grimberg ) 458709403c1SSebastian Grimberg } 459709403c1SSebastian Grimberg 460709403c1SSebastian Grimberg /// Returns an oriented ElemRestriction, $\mathcal{E}$, which extracts the 461709403c1SSebastian Grimberg /// degrees of freedom for each element from the local vector into the 462709403c1SSebastian Grimberg /// element vector or assembles contributions from each element in the 463709403c1SSebastian Grimberg /// element vector to the local vector 464709403c1SSebastian Grimberg /// 465709403c1SSebastian Grimberg /// # arguments 466709403c1SSebastian Grimberg /// 467709403c1SSebastian Grimberg /// * `nelem` - Number of elements described in the offsets array 468709403c1SSebastian Grimberg /// * `elemsize` - Size (number of "nodes") per element 469709403c1SSebastian Grimberg /// * `ncomp` - Number of field components per interpolation node (1 470709403c1SSebastian Grimberg /// for scalar fields) 471709403c1SSebastian Grimberg /// * `compstride` - Stride between components for the same Lvector "node". 472709403c1SSebastian Grimberg /// Data for node `i`, component `j`, element `k` can be 473709403c1SSebastian Grimberg /// found in the Lvector at index 474709403c1SSebastian Grimberg /// `offsets[i + k*elemsize] + j*compstride`. 475709403c1SSebastian Grimberg /// * `lsize` - The size of the Lvector. This vector may be larger 476709403c1SSebastian Grimberg /// than the elements and fields given by this 477709403c1SSebastian Grimberg /// restriction. 478709403c1SSebastian Grimberg /// * `mtype` - Memory type of the offsets array, see CeedMemType 479709403c1SSebastian Grimberg /// * `offsets` - Array of shape `[nelem, elemsize]`. Row `i` holds the 480709403c1SSebastian Grimberg /// ordered list of the offsets (into the input CeedVector) 481709403c1SSebastian Grimberg /// for the unknowns corresponding to element `i`, where 482709403c1SSebastian Grimberg /// `0 <= i < nelem`. All offsets must be in the range 483709403c1SSebastian Grimberg /// `[0, lsize - 1]`. 484709403c1SSebastian Grimberg /// * `orients` - Array of shape `[nelem, elemsize]`. Row `i` holds the 485709403c1SSebastian Grimberg /// ordered list of the orientations for the unknowns 486709403c1SSebastian Grimberg /// corresponding to element `i`, with bool `false` used 487709403c1SSebastian Grimberg /// for positively oriented and `true` to flip the 488709403c1SSebastian Grimberg /// orientation. 489709403c1SSebastian Grimberg /// 490709403c1SSebastian Grimberg /// ``` 491eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, MemType}; 492709403c1SSebastian Grimberg /// # fn main() -> libceed::Result<()> { 493709403c1SSebastian Grimberg /// # let ceed = libceed::Ceed::default_init(); 494709403c1SSebastian Grimberg /// let nelem = 3; 495709403c1SSebastian Grimberg /// let mut ind: Vec<i32> = vec![0; 2 * nelem]; 496709403c1SSebastian Grimberg /// let mut orients: Vec<bool> = vec![false; 2 * nelem]; 497709403c1SSebastian Grimberg /// for i in 0..nelem { 498709403c1SSebastian Grimberg /// ind[2 * i + 0] = i as i32; 499709403c1SSebastian Grimberg /// ind[2 * i + 1] = (i + 1) as i32; 500709403c1SSebastian Grimberg /// orients[2 * i + 0] = (i % 2) > 0; // flip the dofs on element 1, 3, ... 501709403c1SSebastian Grimberg /// orients[2 * i + 1] = (i % 2) > 0; 502709403c1SSebastian Grimberg /// } 503709403c1SSebastian Grimberg /// let r = 504709403c1SSebastian Grimberg /// ceed.oriented_elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &ind, &orients)?; 505709403c1SSebastian Grimberg /// # Ok(()) 506709403c1SSebastian Grimberg /// # } 507709403c1SSebastian Grimberg /// ``` 508*78c2cefaSJeremy L Thompson #[allow(clippy::too_many_arguments)] 509709403c1SSebastian Grimberg pub fn oriented_elem_restriction<'a>( 510709403c1SSebastian Grimberg &self, 511709403c1SSebastian Grimberg nelem: usize, 512709403c1SSebastian Grimberg elemsize: usize, 513709403c1SSebastian Grimberg ncomp: usize, 514709403c1SSebastian Grimberg compstride: usize, 515709403c1SSebastian Grimberg lsize: usize, 516709403c1SSebastian Grimberg mtype: MemType, 517709403c1SSebastian Grimberg offsets: &[i32], 518709403c1SSebastian Grimberg orients: &[bool], 519709403c1SSebastian Grimberg ) -> Result<ElemRestriction<'a>> { 520709403c1SSebastian Grimberg ElemRestriction::create_oriented( 521709403c1SSebastian Grimberg self, nelem, elemsize, ncomp, compstride, lsize, mtype, offsets, orients, 522709403c1SSebastian Grimberg ) 523709403c1SSebastian Grimberg } 524709403c1SSebastian Grimberg 525709403c1SSebastian Grimberg /// Returns a curl-oriented ElemRestriction, $\mathcal{E}$, which extracts 526709403c1SSebastian Grimberg /// the degrees of freedom for each element from the local vector into 527709403c1SSebastian Grimberg /// the element vector or assembles contributions from each element in 528709403c1SSebastian Grimberg /// the element vector to the local vector 529709403c1SSebastian Grimberg /// 530709403c1SSebastian Grimberg /// # arguments 531709403c1SSebastian Grimberg /// 532709403c1SSebastian Grimberg /// * `nelem` - Number of elements described in the offsets array 533709403c1SSebastian Grimberg /// * `elemsize` - Size (number of "nodes") per element 534709403c1SSebastian Grimberg /// * `ncomp` - Number of field components per interpolation node (1 535709403c1SSebastian Grimberg /// for scalar fields) 536709403c1SSebastian Grimberg /// * `compstride` - Stride between components for the same Lvector "node". 537709403c1SSebastian Grimberg /// Data for node `i`, component `j`, element `k` can be 538709403c1SSebastian Grimberg /// found in the Lvector at index 539709403c1SSebastian Grimberg /// `offsets[i + k*elemsize] + j*compstride`. 540709403c1SSebastian Grimberg /// * `lsize` - The size of the Lvector. This vector may be larger 541709403c1SSebastian Grimberg /// than the elements and fields given by this 542709403c1SSebastian Grimberg /// restriction. 543709403c1SSebastian Grimberg /// * `mtype` - Memory type of the offsets array, see CeedMemType 544709403c1SSebastian Grimberg /// * `offsets` - Array of shape `[nelem, elemsize]`. Row `i` holds the 545709403c1SSebastian Grimberg /// ordered list of the offsets (into the input CeedVector) 546709403c1SSebastian Grimberg /// for the unknowns corresponding to element `i`, where 547709403c1SSebastian Grimberg /// `0 <= i < nelem`. All offsets must be in the range 548709403c1SSebastian Grimberg /// `[0, lsize - 1]`. 549709403c1SSebastian Grimberg /// * `curlorients` - Array of shape `[nelem, 3 * elemsize]`. Row `i` holds 550709403c1SSebastian Grimberg /// a row-major tridiagonal matrix (`curlorients[i, 0] = 551709403c1SSebastian Grimberg /// curlorients[i, 3 * elemsize - 1] = 0`, where 552709403c1SSebastian Grimberg /// `0 <= i < nelem`) which is applied to the element 553709403c1SSebastian Grimberg /// unknowns upon restriction. 554709403c1SSebastian Grimberg /// 555709403c1SSebastian Grimberg /// ``` 556eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, MemType}; 557709403c1SSebastian Grimberg /// # fn main() -> libceed::Result<()> { 558709403c1SSebastian Grimberg /// # let ceed = libceed::Ceed::default_init(); 559709403c1SSebastian Grimberg /// let nelem = 3; 560709403c1SSebastian Grimberg /// let mut ind: Vec<i32> = vec![0; 2 * nelem]; 561709403c1SSebastian Grimberg /// let mut curlorients: Vec<i8> = vec![0; 3 * 2 * nelem]; 562709403c1SSebastian Grimberg /// for i in 0..nelem { 563709403c1SSebastian Grimberg /// ind[2 * i + 0] = i as i32; 564709403c1SSebastian Grimberg /// ind[2 * i + 1] = (i + 1) as i32; 565709403c1SSebastian Grimberg /// curlorients[3 * 2 * i] = 0 as i8; 566709403c1SSebastian Grimberg /// curlorients[3 * 2 * (i + 1) - 1] = 0 as i8; 567709403c1SSebastian Grimberg /// if (i % 2 > 0) { 568709403c1SSebastian Grimberg /// // T = [0 -1] 569709403c1SSebastian Grimberg /// // [-1 0] 570709403c1SSebastian Grimberg /// curlorients[3 * 2 * i + 1] = 0 as i8; 571709403c1SSebastian Grimberg /// curlorients[3 * 2 * i + 2] = -1 as i8; 572709403c1SSebastian Grimberg /// curlorients[3 * 2 * i + 3] = -1 as i8; 573709403c1SSebastian Grimberg /// curlorients[3 * 2 * i + 4] = 0 as i8; 574709403c1SSebastian Grimberg /// } else { 575709403c1SSebastian Grimberg /// // T = I 576709403c1SSebastian Grimberg /// curlorients[3 * 2 * i + 1] = 1 as i8; 577709403c1SSebastian Grimberg /// curlorients[3 * 2 * i + 2] = 0 as i8; 578709403c1SSebastian Grimberg /// curlorients[3 * 2 * i + 3] = 0 as i8; 579709403c1SSebastian Grimberg /// curlorients[3 * 2 * i + 4] = 1 as i8; 580709403c1SSebastian Grimberg /// } 581709403c1SSebastian Grimberg /// } 582709403c1SSebastian Grimberg /// let r = ceed.curl_oriented_elem_restriction( 583709403c1SSebastian Grimberg /// nelem, 584709403c1SSebastian Grimberg /// 2, 585709403c1SSebastian Grimberg /// 1, 586709403c1SSebastian Grimberg /// 1, 587709403c1SSebastian Grimberg /// nelem + 1, 588709403c1SSebastian Grimberg /// MemType::Host, 589709403c1SSebastian Grimberg /// &ind, 590709403c1SSebastian Grimberg /// &curlorients, 591709403c1SSebastian Grimberg /// )?; 592709403c1SSebastian Grimberg /// # Ok(()) 593709403c1SSebastian Grimberg /// # } 594709403c1SSebastian Grimberg /// ``` 595*78c2cefaSJeremy L Thompson #[allow(clippy::too_many_arguments)] 596709403c1SSebastian Grimberg pub fn curl_oriented_elem_restriction<'a>( 597709403c1SSebastian Grimberg &self, 598709403c1SSebastian Grimberg nelem: usize, 599709403c1SSebastian Grimberg elemsize: usize, 600709403c1SSebastian Grimberg ncomp: usize, 601709403c1SSebastian Grimberg compstride: usize, 602709403c1SSebastian Grimberg lsize: usize, 603709403c1SSebastian Grimberg mtype: MemType, 604709403c1SSebastian Grimberg offsets: &[i32], 605709403c1SSebastian Grimberg curlorients: &[i8], 606709403c1SSebastian Grimberg ) -> Result<ElemRestriction<'a>> { 607709403c1SSebastian Grimberg ElemRestriction::create_curl_oriented( 608709403c1SSebastian Grimberg self, 609709403c1SSebastian Grimberg nelem, 610709403c1SSebastian Grimberg elemsize, 611709403c1SSebastian Grimberg ncomp, 612709403c1SSebastian Grimberg compstride, 613709403c1SSebastian Grimberg lsize, 614709403c1SSebastian Grimberg mtype, 615709403c1SSebastian Grimberg offsets, 616709403c1SSebastian Grimberg curlorients, 6179df49d7eSJed Brown ) 6189df49d7eSJed Brown } 6199df49d7eSJed Brown 6207ed177dbSJed Brown /// Returns an ElemRestriction, $\mathcal{E}$, from an local vector to 6217ed177dbSJed Brown /// an element vector where data can be indexed from the `strides` array 6229df49d7eSJed Brown /// 6239df49d7eSJed Brown /// # arguments 6249df49d7eSJed Brown /// 6259df49d7eSJed Brown /// * `nelem` - Number of elements described in the offsets array 6269df49d7eSJed Brown /// * `elemsize` - Size (number of "nodes") per element 6279df49d7eSJed Brown /// * `ncomp` - Number of field components per interpolation node (1 6289df49d7eSJed Brown /// for scalar fields) 6299df49d7eSJed Brown /// * `lsize` - The size of the Lvector. This vector may be larger 6309df49d7eSJed Brown /// than the elements and fields given by this restriction. 6319df49d7eSJed Brown /// * `strides` - Array for strides between `[nodes, components, elements]`. 6329df49d7eSJed Brown /// Data for node `i`, component `j`, element `k` can be 6339df49d7eSJed Brown /// found in the Lvector at index 6349df49d7eSJed Brown /// `i*strides[0] + j*strides[1] + k*strides[2]`. 6359df49d7eSJed Brown /// CEED_STRIDES_BACKEND may be used with vectors created 6369df49d7eSJed Brown /// by a Ceed backend. 6379df49d7eSJed Brown /// 6389df49d7eSJed Brown /// ``` 6399df49d7eSJed Brown /// # use libceed::prelude::*; 6404d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 6419df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 6429df49d7eSJed Brown /// let nelem = 3; 6439df49d7eSJed Brown /// let strides: [i32; 3] = [1, 2, 2]; 644c68be7a2SJeremy L Thompson /// let r = ceed.strided_elem_restriction(nelem, 2, 1, nelem * 2, strides)?; 645c68be7a2SJeremy L Thompson /// # Ok(()) 646c68be7a2SJeremy L Thompson /// # } 6479df49d7eSJed Brown /// ``` 648594ef120SJeremy L Thompson pub fn strided_elem_restriction<'a>( 6499df49d7eSJed Brown &self, 6509df49d7eSJed Brown nelem: usize, 6519df49d7eSJed Brown elemsize: usize, 6529df49d7eSJed Brown ncomp: usize, 6539df49d7eSJed Brown lsize: usize, 6549df49d7eSJed Brown strides: [i32; 3], 655594ef120SJeremy L Thompson ) -> Result<ElemRestriction<'a>> { 6569df49d7eSJed Brown ElemRestriction::create_strided(self, nelem, elemsize, ncomp, lsize, strides) 6579df49d7eSJed Brown } 6589df49d7eSJed Brown 6597ed177dbSJed Brown /// Returns an $H^1$ tensor-product Basis 6609df49d7eSJed Brown /// 6619df49d7eSJed Brown /// # arguments 6629df49d7eSJed Brown /// 6639df49d7eSJed Brown /// * `dim` - Topological dimension of element 6649df49d7eSJed Brown /// * `ncomp` - Number of field components (1 for scalar fields) 6659df49d7eSJed Brown /// * `P1d` - Number of Gauss-Lobatto nodes in one dimension. The 6669df49d7eSJed Brown /// polynomial degree of the resulting `Q_k` element is 6679df49d7eSJed Brown /// `k=P-1`. 6689df49d7eSJed Brown /// * `Q1d` - Number of quadrature points in one dimension 6699df49d7eSJed Brown /// * `interp1d` - Row-major `(Q1d * P1d)` matrix expressing the values of 6709df49d7eSJed Brown /// nodal basis functions at quadrature points 6719df49d7eSJed Brown /// * `grad1d` - Row-major `(Q1d * P1d)` matrix expressing derivatives of 6729df49d7eSJed Brown /// nodal basis functions at quadrature points 6739df49d7eSJed Brown /// * `qref1d` - Array of length `Q1d` holding the locations of quadrature 6749df49d7eSJed Brown /// points on the 1D reference element `[-1, 1]` 6759df49d7eSJed Brown /// * `qweight1d` - Array of length `Q1d` holding the quadrature weights on 6769df49d7eSJed Brown /// the reference element 6779df49d7eSJed Brown /// 6789df49d7eSJed Brown /// ``` 6799df49d7eSJed Brown /// # use libceed::prelude::*; 6804d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 6819df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 6829df49d7eSJed Brown /// let interp1d = [ 0.62994317, 0.47255875, -0.14950343, 0.04700152, 6839df49d7eSJed Brown /// -0.07069480, 0.97297619, 0.13253993, -0.03482132, 6849df49d7eSJed Brown /// -0.03482132, 0.13253993, 0.97297619, -0.07069480, 6859df49d7eSJed Brown /// 0.04700152, -0.14950343, 0.47255875, 0.62994317]; 6869df49d7eSJed Brown /// let grad1d = [-2.34183742, 2.78794489, -0.63510411, 0.18899664, 6879df49d7eSJed Brown /// -0.51670214, -0.48795249, 1.33790510, -0.33325047, 6889df49d7eSJed Brown // 0.33325047, -1.33790510, 0.48795249, 0.51670214, 6899df49d7eSJed Brown /// -0.18899664, 0.63510411, -2.78794489, 2.34183742]; 6909df49d7eSJed Brown /// let qref1d = [-0.86113631, -0.33998104, 0.33998104, 0.86113631]; 6919df49d7eSJed Brown /// let qweight1d = [ 0.34785485, 0.65214515, 0.65214515, 0.34785485]; 6929df49d7eSJed Brown /// let b = ceed. 693c68be7a2SJeremy L Thompson /// basis_tensor_H1(2, 1, 4, 4, &interp1d, &grad1d, &qref1d, &qweight1d)?; 694c68be7a2SJeremy L Thompson /// # Ok(()) 695c68be7a2SJeremy L Thompson /// # } 6969df49d7eSJed Brown /// ``` 697*78c2cefaSJeremy L Thompson #[allow(clippy::too_many_arguments)] 698594ef120SJeremy L Thompson pub fn basis_tensor_H1<'a>( 6999df49d7eSJed Brown &self, 7009df49d7eSJed Brown dim: usize, 7019df49d7eSJed Brown ncomp: usize, 7029df49d7eSJed Brown P1d: usize, 7039df49d7eSJed Brown Q1d: usize, 70480a9ef05SNatalie Beams interp1d: &[crate::Scalar], 70580a9ef05SNatalie Beams grad1d: &[crate::Scalar], 70680a9ef05SNatalie Beams qref1d: &[crate::Scalar], 70780a9ef05SNatalie Beams qweight1d: &[crate::Scalar], 708594ef120SJeremy L Thompson ) -> Result<Basis<'a>> { 7099df49d7eSJed Brown Basis::create_tensor_H1( 7109df49d7eSJed Brown self, dim, ncomp, P1d, Q1d, interp1d, grad1d, qref1d, qweight1d, 7119df49d7eSJed Brown ) 7129df49d7eSJed Brown } 7139df49d7eSJed Brown 7147ed177dbSJed Brown /// Returns an $H^1$ Lagrange tensor-product Basis 7159df49d7eSJed Brown /// 7169df49d7eSJed Brown /// # arguments 7179df49d7eSJed Brown /// 7189df49d7eSJed Brown /// * `dim` - Topological dimension of element 7199df49d7eSJed Brown /// * `ncomp` - Number of field components (1 for scalar fields) 7209df49d7eSJed Brown /// * `P` - Number of Gauss-Lobatto nodes in one dimension. The 7219df49d7eSJed Brown /// polynomial degree of the resulting `Q_k` element is `k=P-1`. 7229df49d7eSJed Brown /// * `Q` - Number of quadrature points in one dimension 7239df49d7eSJed Brown /// * `qmode` - Distribution of the `Q` quadrature points (affects order of 7249df49d7eSJed Brown /// accuracy for the quadrature) 7259df49d7eSJed Brown /// 7269df49d7eSJed Brown /// ``` 727eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, QuadMode}; 7284d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 7299df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 730c68be7a2SJeremy L Thompson /// let b = ceed.basis_tensor_H1_Lagrange(2, 1, 3, 4, QuadMode::Gauss)?; 731c68be7a2SJeremy L Thompson /// # Ok(()) 732c68be7a2SJeremy L Thompson /// # } 7339df49d7eSJed Brown /// ``` 734594ef120SJeremy L Thompson pub fn basis_tensor_H1_Lagrange<'a>( 7359df49d7eSJed Brown &self, 7369df49d7eSJed Brown dim: usize, 7379df49d7eSJed Brown ncomp: usize, 7389df49d7eSJed Brown P: usize, 7399df49d7eSJed Brown Q: usize, 7409df49d7eSJed Brown qmode: QuadMode, 741594ef120SJeremy L Thompson ) -> Result<Basis<'a>> { 7429df49d7eSJed Brown Basis::create_tensor_H1_Lagrange(self, dim, ncomp, P, Q, qmode) 7439df49d7eSJed Brown } 7449df49d7eSJed Brown 7457ed177dbSJed Brown /// Returns an $H-1$ Basis 7469df49d7eSJed Brown /// 7479df49d7eSJed Brown /// # arguments 7489df49d7eSJed Brown /// 7499df49d7eSJed Brown /// * `topo` - Topology of element, e.g. hypercube, simplex, ect 7509df49d7eSJed Brown /// * `ncomp` - Number of field components (1 for scalar fields) 7519df49d7eSJed Brown /// * `nnodes` - Total number of nodes 7529df49d7eSJed Brown /// * `nqpts` - Total number of quadrature points 7539df49d7eSJed Brown /// * `interp` - Row-major `(nqpts * nnodes)` matrix expressing the values of 7549df49d7eSJed Brown /// nodal basis functions at quadrature points 75597c1c57aSSebastian Grimberg /// * `grad` - Row-major `(dim * nqpts * nnodes)` matrix expressing 7569df49d7eSJed Brown /// derivatives of nodal basis functions at quadrature points 7579df49d7eSJed Brown /// * `qref` - Array of length `nqpts` holding the locations of quadrature 7589df49d7eSJed Brown /// points on the reference element `[-1, 1]` 7599df49d7eSJed Brown /// * `qweight` - Array of length `nqpts` holding the quadrature weights on 7609df49d7eSJed Brown /// the reference element 7619df49d7eSJed Brown /// 7629df49d7eSJed Brown /// ``` 763eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, ElemTopology}; 7644d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 7659df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 7669df49d7eSJed Brown /// let interp = [ 7679df49d7eSJed Brown /// 0.12000000, 7689df49d7eSJed Brown /// 0.48000000, 7699df49d7eSJed Brown /// -0.12000000, 7709df49d7eSJed Brown /// 0.48000000, 7719df49d7eSJed Brown /// 0.16000000, 7729df49d7eSJed Brown /// -0.12000000, 7739df49d7eSJed Brown /// -0.12000000, 7749df49d7eSJed Brown /// 0.48000000, 7759df49d7eSJed Brown /// 0.12000000, 7769df49d7eSJed Brown /// 0.16000000, 7779df49d7eSJed Brown /// 0.48000000, 7789df49d7eSJed Brown /// -0.12000000, 7799df49d7eSJed Brown /// -0.11111111, 7809df49d7eSJed Brown /// 0.44444444, 7819df49d7eSJed Brown /// -0.11111111, 7829df49d7eSJed Brown /// 0.44444444, 7839df49d7eSJed Brown /// 0.44444444, 7849df49d7eSJed Brown /// -0.11111111, 7859df49d7eSJed Brown /// -0.12000000, 7869df49d7eSJed Brown /// 0.16000000, 7879df49d7eSJed Brown /// -0.12000000, 7889df49d7eSJed Brown /// 0.48000000, 7899df49d7eSJed Brown /// 0.48000000, 7909df49d7eSJed Brown /// 0.12000000, 7919df49d7eSJed Brown /// ]; 7929df49d7eSJed Brown /// let grad = [ 7939df49d7eSJed Brown /// -1.40000000, 7949df49d7eSJed Brown /// 1.60000000, 7959df49d7eSJed Brown /// -0.20000000, 7969df49d7eSJed Brown /// -0.80000000, 7979df49d7eSJed Brown /// 0.80000000, 7989df49d7eSJed Brown /// 0.00000000, 7999df49d7eSJed Brown /// 0.20000000, 8009df49d7eSJed Brown /// -1.60000000, 8019df49d7eSJed Brown /// 1.40000000, 8029df49d7eSJed Brown /// -0.80000000, 8039df49d7eSJed Brown /// 0.80000000, 8049df49d7eSJed Brown /// 0.00000000, 8059df49d7eSJed Brown /// -0.33333333, 8069df49d7eSJed Brown /// 0.00000000, 8079df49d7eSJed Brown /// 0.33333333, 8089df49d7eSJed Brown /// -1.33333333, 8099df49d7eSJed Brown /// 1.33333333, 8109df49d7eSJed Brown /// 0.00000000, 8119df49d7eSJed Brown /// 0.20000000, 8129df49d7eSJed Brown /// 0.00000000, 8139df49d7eSJed Brown /// -0.20000000, 8149df49d7eSJed Brown /// -2.40000000, 8159df49d7eSJed Brown /// 2.40000000, 8169df49d7eSJed Brown /// 0.00000000, 8179df49d7eSJed Brown /// -1.40000000, 8189df49d7eSJed Brown /// -0.80000000, 8199df49d7eSJed Brown /// 0.00000000, 8209df49d7eSJed Brown /// 1.60000000, 8219df49d7eSJed Brown /// 0.80000000, 8229df49d7eSJed Brown /// -0.20000000, 8239df49d7eSJed Brown /// 0.20000000, 8249df49d7eSJed Brown /// -2.40000000, 8259df49d7eSJed Brown /// 0.00000000, 8269df49d7eSJed Brown /// 0.00000000, 8279df49d7eSJed Brown /// 2.40000000, 8289df49d7eSJed Brown /// -0.20000000, 8299df49d7eSJed Brown /// -0.33333333, 8309df49d7eSJed Brown /// -1.33333333, 8319df49d7eSJed Brown /// 0.00000000, 8329df49d7eSJed Brown /// 0.00000000, 8339df49d7eSJed Brown /// 1.33333333, 8349df49d7eSJed Brown /// 0.33333333, 8359df49d7eSJed Brown /// 0.20000000, 8369df49d7eSJed Brown /// -0.80000000, 8379df49d7eSJed Brown /// 0.00000000, 8389df49d7eSJed Brown /// -1.60000000, 8399df49d7eSJed Brown /// 0.80000000, 8409df49d7eSJed Brown /// 1.40000000, 8419df49d7eSJed Brown /// ]; 8429df49d7eSJed Brown /// let qref = [ 8439df49d7eSJed Brown /// 0.20000000, 0.60000000, 0.33333333, 0.20000000, 0.20000000, 0.20000000, 0.33333333, 8449df49d7eSJed Brown /// 0.60000000, 8459df49d7eSJed Brown /// ]; 8469df49d7eSJed Brown /// let qweight = [0.26041667, 0.26041667, -0.28125000, 0.26041667]; 847c68be7a2SJeremy L Thompson /// let b = ceed.basis_H1( 8489df49d7eSJed Brown /// ElemTopology::Triangle, 8499df49d7eSJed Brown /// 1, 8509df49d7eSJed Brown /// 6, 8519df49d7eSJed Brown /// 4, 8529df49d7eSJed Brown /// &interp, 8539df49d7eSJed Brown /// &grad, 8549df49d7eSJed Brown /// &qref, 8559df49d7eSJed Brown /// &qweight, 856c68be7a2SJeremy L Thompson /// )?; 857c68be7a2SJeremy L Thompson /// # Ok(()) 858c68be7a2SJeremy L Thompson /// # } 8599df49d7eSJed Brown /// ``` 860*78c2cefaSJeremy L Thompson #[allow(clippy::too_many_arguments)] 861594ef120SJeremy L Thompson pub fn basis_H1<'a>( 8629df49d7eSJed Brown &self, 8639df49d7eSJed Brown topo: ElemTopology, 8649df49d7eSJed Brown ncomp: usize, 8659df49d7eSJed Brown nnodes: usize, 8669df49d7eSJed Brown nqpts: usize, 86780a9ef05SNatalie Beams interp: &[crate::Scalar], 86880a9ef05SNatalie Beams grad: &[crate::Scalar], 86980a9ef05SNatalie Beams qref: &[crate::Scalar], 87080a9ef05SNatalie Beams qweight: &[crate::Scalar], 871594ef120SJeremy L Thompson ) -> Result<Basis<'a>> { 8729df49d7eSJed Brown Basis::create_H1( 8739df49d7eSJed Brown self, topo, ncomp, nnodes, nqpts, interp, grad, qref, qweight, 8749df49d7eSJed Brown ) 8759df49d7eSJed Brown } 8769df49d7eSJed Brown 87797c1c57aSSebastian Grimberg /// Returns an $H(div)$ Basis 87897c1c57aSSebastian Grimberg /// 87997c1c57aSSebastian Grimberg /// # arguments 88097c1c57aSSebastian Grimberg /// 88197c1c57aSSebastian Grimberg /// * `topo` - Topology of element, e.g. hypercube, simplex, ect 88297c1c57aSSebastian Grimberg /// * `ncomp` - Number of field components (1 for scalar fields) 88397c1c57aSSebastian Grimberg /// * `nnodes` - Total number of nodes 88497c1c57aSSebastian Grimberg /// * `nqpts` - Total number of quadrature points 88597c1c57aSSebastian Grimberg /// * `interp` - Row-major `(dim * nqpts * nnodes)` matrix expressing the 88697c1c57aSSebastian Grimberg /// values of basis functions at quadrature points 88797c1c57aSSebastian Grimberg /// * `div` - Row-major `(nqpts * nnodes)` matrix expressing the 88897c1c57aSSebastian Grimberg /// divergence of basis functions at quadrature points 88997c1c57aSSebastian Grimberg /// * `qref` - Array of length `nqpts` holding the locations of quadrature 89097c1c57aSSebastian Grimberg /// points on the reference element `[-1, 1]` 89197c1c57aSSebastian Grimberg /// * `qweight` - Array of length `nqpts` holding the quadrature weights on 89297c1c57aSSebastian Grimberg /// the reference element 89397c1c57aSSebastian Grimberg /// 89497c1c57aSSebastian Grimberg /// ``` 895eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, ElemTopology}; 89697c1c57aSSebastian Grimberg /// # fn main() -> libceed::Result<()> { 89797c1c57aSSebastian Grimberg /// # let ceed = libceed::Ceed::default_init(); 89897c1c57aSSebastian Grimberg /// let interp = [ 89997c1c57aSSebastian Grimberg /// 0.00000000, 90097c1c57aSSebastian Grimberg /// -1.57735027, 90197c1c57aSSebastian Grimberg /// 0.57735027, 90297c1c57aSSebastian Grimberg /// 0.00000000, 90397c1c57aSSebastian Grimberg /// 0.00000000, 90497c1c57aSSebastian Grimberg /// -1.57735027, 90597c1c57aSSebastian Grimberg /// 0.57735027, 90697c1c57aSSebastian Grimberg /// 0.00000000, 90797c1c57aSSebastian Grimberg /// 0.00000000, 90897c1c57aSSebastian Grimberg /// -1.57735027, 90997c1c57aSSebastian Grimberg /// 0.57735027, 91097c1c57aSSebastian Grimberg /// 0.00000000, 91197c1c57aSSebastian Grimberg /// 0.00000000, 91297c1c57aSSebastian Grimberg /// -0.42264973, 91397c1c57aSSebastian Grimberg /// -0.57735027, 91497c1c57aSSebastian Grimberg /// 0.00000000, 91597c1c57aSSebastian Grimberg /// 0.42264973, 91697c1c57aSSebastian Grimberg /// 0.00000000, 91797c1c57aSSebastian Grimberg /// 0.00000000, 91897c1c57aSSebastian Grimberg /// 0.57735027, 91997c1c57aSSebastian Grimberg /// 0.42264973, 92097c1c57aSSebastian Grimberg /// 0.00000000, 92197c1c57aSSebastian Grimberg /// 0.00000000, 92297c1c57aSSebastian Grimberg /// 0.57735027, 92397c1c57aSSebastian Grimberg /// 1.57735027, 92497c1c57aSSebastian Grimberg /// 0.00000000, 92597c1c57aSSebastian Grimberg /// 0.00000000, 92697c1c57aSSebastian Grimberg /// -0.57735027, 92797c1c57aSSebastian Grimberg /// 1.57735027, 92897c1c57aSSebastian Grimberg /// 0.00000000, 92997c1c57aSSebastian Grimberg /// 0.00000000, 93097c1c57aSSebastian Grimberg /// -0.57735027, 93197c1c57aSSebastian Grimberg /// ]; 93297c1c57aSSebastian Grimberg /// let div = [ 93397c1c57aSSebastian Grimberg /// -1.00000000, 93497c1c57aSSebastian Grimberg /// 1.00000000, 93597c1c57aSSebastian Grimberg /// -1.00000000, 93697c1c57aSSebastian Grimberg /// 1.00000000, 93797c1c57aSSebastian Grimberg /// -1.00000000, 93897c1c57aSSebastian Grimberg /// 1.00000000, 93997c1c57aSSebastian Grimberg /// -1.00000000, 94097c1c57aSSebastian Grimberg /// 1.00000000, 94197c1c57aSSebastian Grimberg /// -1.00000000, 94297c1c57aSSebastian Grimberg /// 1.00000000, 94397c1c57aSSebastian Grimberg /// -1.00000000, 94497c1c57aSSebastian Grimberg /// 1.00000000, 94597c1c57aSSebastian Grimberg /// -1.00000000, 94697c1c57aSSebastian Grimberg /// 1.00000000, 94797c1c57aSSebastian Grimberg /// -1.00000000, 94897c1c57aSSebastian Grimberg /// 1.00000000, 94997c1c57aSSebastian Grimberg /// ]; 95097c1c57aSSebastian Grimberg /// let qref = [ 95197c1c57aSSebastian Grimberg /// 0.57735026, 0.57735026, 0.57735026, 0.57735026, 0.57735026, 0.57735026, 0.57735026, 95297c1c57aSSebastian Grimberg /// 0.57735026, 95397c1c57aSSebastian Grimberg /// ]; 95497c1c57aSSebastian Grimberg /// let qweight = [1.00000000, 1.00000000, 1.00000000, 1.00000000]; 95597c1c57aSSebastian Grimberg /// let b = ceed.basis_Hdiv(ElemTopology::Quad, 1, 4, 4, &interp, &div, &qref, &qweight)?; 95697c1c57aSSebastian Grimberg /// # Ok(()) 95797c1c57aSSebastian Grimberg /// # } 95897c1c57aSSebastian Grimberg /// ``` 959*78c2cefaSJeremy L Thompson #[allow(clippy::too_many_arguments)] 96097c1c57aSSebastian Grimberg pub fn basis_Hdiv<'a>( 96197c1c57aSSebastian Grimberg &self, 96297c1c57aSSebastian Grimberg topo: ElemTopology, 96397c1c57aSSebastian Grimberg ncomp: usize, 96497c1c57aSSebastian Grimberg nnodes: usize, 96597c1c57aSSebastian Grimberg nqpts: usize, 96697c1c57aSSebastian Grimberg interp: &[crate::Scalar], 96797c1c57aSSebastian Grimberg div: &[crate::Scalar], 96897c1c57aSSebastian Grimberg qref: &[crate::Scalar], 96997c1c57aSSebastian Grimberg qweight: &[crate::Scalar], 97097c1c57aSSebastian Grimberg ) -> Result<Basis<'a>> { 97197c1c57aSSebastian Grimberg Basis::create_Hdiv(self, topo, ncomp, nnodes, nqpts, interp, div, qref, qweight) 97297c1c57aSSebastian Grimberg } 97397c1c57aSSebastian Grimberg 97497c1c57aSSebastian Grimberg /// Returns an $H(curl)$ Basis 97597c1c57aSSebastian Grimberg /// 97697c1c57aSSebastian Grimberg /// # arguments 97797c1c57aSSebastian Grimberg /// 97897c1c57aSSebastian Grimberg /// * `topo` - Topology of element, e.g. hypercube, simplex, ect 97997c1c57aSSebastian Grimberg /// * `ncomp` - Number of field components (1 for scalar fields) 98097c1c57aSSebastian Grimberg /// * `nnodes` - Total number of nodes 98197c1c57aSSebastian Grimberg /// * `nqpts` - Total number of quadrature points 98297c1c57aSSebastian Grimberg /// * `interp` - Row-major `(dim * nqpts * nnodes)` matrix expressing the 98397c1c57aSSebastian Grimberg /// values of basis functions at quadrature points 98497c1c57aSSebastian Grimberg /// * `curl` - Row-major `(curl_comp * nqpts * nnodes)`, `curl_comp = 1 if 98597c1c57aSSebastian Grimberg /// dim < 3 else dim` matrix expressing the curl of basis 98697c1c57aSSebastian Grimberg /// functions at quadrature points 98797c1c57aSSebastian Grimberg /// * `qref` - Array of length `nqpts` holding the locations of quadrature 98897c1c57aSSebastian Grimberg /// points on the reference element `[-1, 1]` 98997c1c57aSSebastian Grimberg /// * `qweight` - Array of length `nqpts` holding the quadrature weights on 99097c1c57aSSebastian Grimberg /// the reference element 99197c1c57aSSebastian Grimberg /// 99297c1c57aSSebastian Grimberg /// ``` 993eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, ElemTopology}; 99497c1c57aSSebastian Grimberg /// # fn main() -> libceed::Result<()> { 99597c1c57aSSebastian Grimberg /// # let ceed = libceed::Ceed::default_init(); 99697c1c57aSSebastian Grimberg /// let interp = [ 99797c1c57aSSebastian Grimberg /// -0.20000000, 99897c1c57aSSebastian Grimberg /// 0.20000000, 99997c1c57aSSebastian Grimberg /// 0.80000000, 100097c1c57aSSebastian Grimberg /// -0.20000000, 100197c1c57aSSebastian Grimberg /// 0.20000000, 100297c1c57aSSebastian Grimberg /// 0.80000000, 100397c1c57aSSebastian Grimberg /// -0.33333333, 100497c1c57aSSebastian Grimberg /// 0.33333333, 100597c1c57aSSebastian Grimberg /// 0.66666667, 100697c1c57aSSebastian Grimberg /// -0.60000000, 100797c1c57aSSebastian Grimberg /// 0.60000000, 100897c1c57aSSebastian Grimberg /// 0.40000000, 100997c1c57aSSebastian Grimberg /// 0.20000000, 101097c1c57aSSebastian Grimberg /// 0.80000000, 101197c1c57aSSebastian Grimberg /// 0.20000000, 101297c1c57aSSebastian Grimberg /// 0.60000000, 101397c1c57aSSebastian Grimberg /// 0.40000000, 101497c1c57aSSebastian Grimberg /// 0.60000000, 101597c1c57aSSebastian Grimberg /// 0.33333333, 101697c1c57aSSebastian Grimberg /// 0.66666667, 101797c1c57aSSebastian Grimberg /// 0.33333333, 101897c1c57aSSebastian Grimberg /// 0.20000000, 101997c1c57aSSebastian Grimberg /// 0.80000000, 102097c1c57aSSebastian Grimberg /// 0.20000000, 102197c1c57aSSebastian Grimberg /// ]; 102297c1c57aSSebastian Grimberg /// let curl = [ 102397c1c57aSSebastian Grimberg /// 2.00000000, 102497c1c57aSSebastian Grimberg /// -2.00000000, 102597c1c57aSSebastian Grimberg /// -2.00000000, 102697c1c57aSSebastian Grimberg /// 2.00000000, 102797c1c57aSSebastian Grimberg /// -2.00000000, 102897c1c57aSSebastian Grimberg /// -2.00000000, 102997c1c57aSSebastian Grimberg /// 2.00000000, 103097c1c57aSSebastian Grimberg /// -2.00000000, 103197c1c57aSSebastian Grimberg /// -2.00000000, 103297c1c57aSSebastian Grimberg /// 2.00000000, 103397c1c57aSSebastian Grimberg /// -2.00000000, 103497c1c57aSSebastian Grimberg /// -2.00000000, 103597c1c57aSSebastian Grimberg /// ]; 103697c1c57aSSebastian Grimberg /// let qref = [ 103797c1c57aSSebastian Grimberg /// 0.20000000, 0.60000000, 0.33333333, 0.20000000, 0.20000000, 0.20000000, 0.33333333, 103897c1c57aSSebastian Grimberg /// 0.60000000, 103997c1c57aSSebastian Grimberg /// ]; 104097c1c57aSSebastian Grimberg /// let qweight = [0.26041667, 0.26041667, -0.28125000, 0.26041667]; 104197c1c57aSSebastian Grimberg /// let b = ceed.basis_Hcurl( 104297c1c57aSSebastian Grimberg /// ElemTopology::Triangle, 104397c1c57aSSebastian Grimberg /// 1, 104497c1c57aSSebastian Grimberg /// 3, 104597c1c57aSSebastian Grimberg /// 4, 104697c1c57aSSebastian Grimberg /// &interp, 104797c1c57aSSebastian Grimberg /// &curl, 104897c1c57aSSebastian Grimberg /// &qref, 104997c1c57aSSebastian Grimberg /// &qweight, 105097c1c57aSSebastian Grimberg /// )?; 105197c1c57aSSebastian Grimberg /// # Ok(()) 105297c1c57aSSebastian Grimberg /// # } 105397c1c57aSSebastian Grimberg /// ``` 1054*78c2cefaSJeremy L Thompson #[allow(clippy::too_many_arguments)] 105597c1c57aSSebastian Grimberg pub fn basis_Hcurl<'a>( 105697c1c57aSSebastian Grimberg &self, 105797c1c57aSSebastian Grimberg topo: ElemTopology, 105897c1c57aSSebastian Grimberg ncomp: usize, 105997c1c57aSSebastian Grimberg nnodes: usize, 106097c1c57aSSebastian Grimberg nqpts: usize, 106197c1c57aSSebastian Grimberg interp: &[crate::Scalar], 106297c1c57aSSebastian Grimberg curl: &[crate::Scalar], 106397c1c57aSSebastian Grimberg qref: &[crate::Scalar], 106497c1c57aSSebastian Grimberg qweight: &[crate::Scalar], 106597c1c57aSSebastian Grimberg ) -> Result<Basis<'a>> { 106697c1c57aSSebastian Grimberg Basis::create_Hcurl( 106797c1c57aSSebastian Grimberg self, topo, ncomp, nnodes, nqpts, interp, curl, qref, qweight, 106897c1c57aSSebastian Grimberg ) 106997c1c57aSSebastian Grimberg } 107097c1c57aSSebastian Grimberg 10717ed177dbSJed Brown /// Returns a QFunction for evaluating interior (volumetric) terms 10727ed177dbSJed Brown /// of a weak form corresponding to the $L^2$ inner product 10737ed177dbSJed Brown /// 10747ed177dbSJed Brown /// $$ 10757ed177dbSJed Brown /// \langle v, F(u) \rangle = \int_\Omega v \cdot f_0 \left( u, \nabla u \right) + \left( \nabla v \right) : f_1 \left( u, \nabla u \right), 10767ed177dbSJed Brown /// $$ 10777ed177dbSJed Brown /// 10787ed177dbSJed Brown /// where $v \cdot f_0$ represents contraction over fields and $\nabla v : f_1$ 10797ed177dbSJed Brown /// represents contraction over both fields and spatial dimensions. 10809df49d7eSJed Brown /// 10819df49d7eSJed Brown /// # arguments 10829df49d7eSJed Brown /// 10839df49d7eSJed Brown /// * `vlength` - Vector length. Caller must ensure that number of 10849df49d7eSJed Brown /// quadrature points is a multiple of vlength. 10857ed177dbSJed Brown /// * `f` - Boxed closure to evaluate weak form at quadrature points. 10869df49d7eSJed Brown /// 10879df49d7eSJed Brown /// ``` 1088eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, QFunctionInputs, QFunctionOutputs}; 10894d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 10909df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 10919df49d7eSJed Brown /// let mut user_f = |[u, weights, ..]: QFunctionInputs, [v, ..]: QFunctionOutputs| { 10929df49d7eSJed Brown /// // Iterate over quadrature points 10939df49d7eSJed Brown /// v.iter_mut() 10949df49d7eSJed Brown /// .zip(u.iter().zip(weights.iter())) 10959df49d7eSJed Brown /// .for_each(|(v, (u, w))| *v = u * w); 10969df49d7eSJed Brown /// 10979df49d7eSJed Brown /// // Return clean error code 10989df49d7eSJed Brown /// 0 10999df49d7eSJed Brown /// }; 11009df49d7eSJed Brown /// 1101c68be7a2SJeremy L Thompson /// let qf = ceed.q_function_interior(1, Box::new(user_f))?; 1102c68be7a2SJeremy L Thompson /// # Ok(()) 1103c68be7a2SJeremy L Thompson /// # } 11049df49d7eSJed Brown /// ``` 1105594ef120SJeremy L Thompson pub fn q_function_interior<'a>( 11069df49d7eSJed Brown &self, 11079df49d7eSJed Brown vlength: usize, 11089df49d7eSJed Brown f: Box<qfunction::QFunctionUserClosure>, 1109594ef120SJeremy L Thompson ) -> Result<QFunction<'a>> { 11109df49d7eSJed Brown QFunction::create(self, vlength, f) 11119df49d7eSJed Brown } 11129df49d7eSJed Brown 11137ed177dbSJed Brown /// Returns a QFunction for evaluating interior (volumetric) terms 11149df49d7eSJed Brown /// created by name 11159df49d7eSJed Brown /// 11167ed177dbSJed Brown /// # arguments 11177ed177dbSJed Brown /// 11187ed177dbSJed Brown /// * `name` - name of QFunction from libCEED gallery 11197ed177dbSJed Brown /// 11209df49d7eSJed Brown /// ``` 11219df49d7eSJed Brown /// # use libceed::prelude::*; 11224d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 11239df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 1124c68be7a2SJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 1125c68be7a2SJeremy L Thompson /// # Ok(()) 1126c68be7a2SJeremy L Thompson /// # } 11279df49d7eSJed Brown /// ``` 1128594ef120SJeremy L Thompson pub fn q_function_interior_by_name<'a>(&self, name: &str) -> Result<QFunctionByName<'a>> { 11299df49d7eSJed Brown QFunctionByName::create(self, name) 11309df49d7eSJed Brown } 11319df49d7eSJed Brown 11327ed177dbSJed Brown /// Returns an Operator and associate a QFunction. A Basis and 11337ed177dbSJed Brown /// ElemRestriction can be associated with QFunction fields via 11349df49d7eSJed Brown /// set_field(). 11359df49d7eSJed Brown /// 11367ed177dbSJed Brown /// # arguments 11377ed177dbSJed Brown /// 11389df49d7eSJed Brown /// * `qf` - QFunction defining the action of the operator at quadrature 11399df49d7eSJed Brown /// points 11409df49d7eSJed Brown /// * `dqf` - QFunction defining the action of the Jacobian of the qf (or 11419df49d7eSJed Brown /// qfunction_none) 11429df49d7eSJed Brown /// * `dqfT` - QFunction defining the action of the transpose of the 11439df49d7eSJed Brown /// Jacobian of the qf (or qfunction_none) 11449df49d7eSJed Brown /// 11459df49d7eSJed Brown /// ``` 1146eb07d68fSJeremy L Thompson /// # use libceed::{prelude::*, QFunctionOpt}; 11474d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 11489df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 1149c68be7a2SJeremy L Thompson /// let qf = ceed.q_function_interior_by_name("Mass1DBuild")?; 1150c68be7a2SJeremy L Thompson /// let op = ceed.operator(&qf, QFunctionOpt::None, QFunctionOpt::None)?; 1151c68be7a2SJeremy L Thompson /// # Ok(()) 1152c68be7a2SJeremy L Thompson /// # } 11539df49d7eSJed Brown /// ``` 1154594ef120SJeremy L Thompson pub fn operator<'a, 'b>( 11559df49d7eSJed Brown &self, 11569df49d7eSJed Brown qf: impl Into<QFunctionOpt<'b>>, 11579df49d7eSJed Brown dqf: impl Into<QFunctionOpt<'b>>, 11589df49d7eSJed Brown dqfT: impl Into<QFunctionOpt<'b>>, 1159594ef120SJeremy L Thompson ) -> Result<Operator<'a>> { 11609df49d7eSJed Brown Operator::create(self, qf, dqf, dqfT) 11619df49d7eSJed Brown } 11629df49d7eSJed Brown 11639df49d7eSJed Brown /// Returns an Operator that composes the action of several Operators 11649df49d7eSJed Brown /// 11659df49d7eSJed Brown /// ``` 11669df49d7eSJed Brown /// # use libceed::prelude::*; 11674d27c890SJeremy L Thompson /// # fn main() -> libceed::Result<()> { 11689df49d7eSJed Brown /// # let ceed = libceed::Ceed::default_init(); 1169c68be7a2SJeremy L Thompson /// let op = ceed.composite_operator()?; 1170c68be7a2SJeremy L Thompson /// # Ok(()) 1171c68be7a2SJeremy L Thompson /// # } 11729df49d7eSJed Brown /// ``` 1173594ef120SJeremy L Thompson pub fn composite_operator<'a>(&self) -> Result<CompositeOperator<'a>> { 11749df49d7eSJed Brown CompositeOperator::create(self) 11759df49d7eSJed Brown } 11769df49d7eSJed Brown } 11779df49d7eSJed Brown 11789df49d7eSJed Brown // ----------------------------------------------------------------------------- 11799df49d7eSJed Brown // Tests 11809df49d7eSJed Brown // ----------------------------------------------------------------------------- 11819df49d7eSJed Brown #[cfg(test)] 11829df49d7eSJed Brown mod tests { 11839df49d7eSJed Brown use super::*; 11849df49d7eSJed Brown 118589d15d5fSJeremy L Thompson fn ceed_t501() -> Result<()> { 11869df49d7eSJed Brown let resource = "/cpu/self/ref/blocked"; 11879df49d7eSJed Brown let ceed = Ceed::init(resource); 11889df49d7eSJed Brown let nelem = 4; 11899df49d7eSJed Brown let p = 3; 11909df49d7eSJed Brown let q = 4; 11919df49d7eSJed Brown let ndofs = p * nelem - nelem + 1; 11929df49d7eSJed Brown 11939df49d7eSJed Brown // Vectors 11949df49d7eSJed Brown let x = ceed.vector_from_slice(&[-1., -0.5, 0.0, 0.5, 1.0])?; 11959df49d7eSJed Brown let mut qdata = ceed.vector(nelem * q)?; 11969df49d7eSJed Brown qdata.set_value(0.0)?; 11979df49d7eSJed Brown let mut u = ceed.vector(ndofs)?; 11989df49d7eSJed Brown u.set_value(1.0)?; 11999df49d7eSJed Brown let mut v = ceed.vector(ndofs)?; 12009df49d7eSJed Brown v.set_value(0.0)?; 12019df49d7eSJed Brown 12029df49d7eSJed Brown // Restrictions 12039df49d7eSJed Brown let mut indx: Vec<i32> = vec![0; 2 * nelem]; 12049df49d7eSJed Brown for i in 0..nelem { 12051ce8139fSJeremy L Thompson for j in 0..2 { 12061ce8139fSJeremy L Thompson indx[2 * i + j] = (i + j) as i32; 12071ce8139fSJeremy L Thompson } 12089df49d7eSJed Brown } 12099df49d7eSJed Brown let rx = ceed.elem_restriction(nelem, 2, 1, 1, nelem + 1, MemType::Host, &indx)?; 12109df49d7eSJed Brown let mut indu: Vec<i32> = vec![0; p * nelem]; 12119df49d7eSJed Brown for i in 0..nelem { 12121ce8139fSJeremy L Thompson for j in 0..p { 12131ce8139fSJeremy L Thompson indu[p * i + j] = (i + j) as i32; 12149df49d7eSJed Brown } 12151ce8139fSJeremy L Thompson } 12161ce8139fSJeremy L Thompson let ru = ceed.elem_restriction(nelem, p, 1, 1, ndofs, MemType::Host, &indu)?; 12179df49d7eSJed Brown let strides: [i32; 3] = [1, q as i32, q as i32]; 12189df49d7eSJed Brown let rq = ceed.strided_elem_restriction(nelem, q, 1, q * nelem, strides)?; 12199df49d7eSJed Brown 12209df49d7eSJed Brown // Bases 12219df49d7eSJed Brown let bx = ceed.basis_tensor_H1_Lagrange(1, 1, 2, q, QuadMode::Gauss)?; 12229df49d7eSJed Brown let bu = ceed.basis_tensor_H1_Lagrange(1, 1, p, q, QuadMode::Gauss)?; 12239df49d7eSJed Brown 12249df49d7eSJed Brown // Build quadrature data 12259df49d7eSJed Brown let qf_build = ceed.q_function_interior_by_name("Mass1DBuild")?; 12269df49d7eSJed Brown ceed.operator(&qf_build, QFunctionOpt::None, QFunctionOpt::None)? 12279df49d7eSJed Brown .field("dx", &rx, &bx, VectorOpt::Active)? 12289df49d7eSJed Brown .field("weights", ElemRestrictionOpt::None, &bx, VectorOpt::None)? 1229356036faSJeremy L Thompson .field("qdata", &rq, BasisOpt::None, VectorOpt::Active)? 12309df49d7eSJed Brown .apply(&x, &mut qdata)?; 12319df49d7eSJed Brown 12329df49d7eSJed Brown // Mass operator 12339df49d7eSJed Brown let qf_mass = ceed.q_function_interior_by_name("MassApply")?; 12349df49d7eSJed Brown let op_mass = ceed 12359df49d7eSJed Brown .operator(&qf_mass, QFunctionOpt::None, QFunctionOpt::None)? 12369df49d7eSJed Brown .field("u", &ru, &bu, VectorOpt::Active)? 1237356036faSJeremy L Thompson .field("qdata", &rq, BasisOpt::None, &qdata)? 12386f97ff0aSJeremy L Thompson .field("v", &ru, &bu, VectorOpt::Active)? 12396f97ff0aSJeremy L Thompson .check()?; 12409df49d7eSJed Brown 12419df49d7eSJed Brown v.set_value(0.0)?; 12429df49d7eSJed Brown op_mass.apply(&u, &mut v)?; 12439df49d7eSJed Brown 12449df49d7eSJed Brown // Check 1245e78171edSJeremy L Thompson let sum: Scalar = v.view()?.iter().sum(); 12461ce8139fSJeremy L Thompson let error: Scalar = (sum - 2.0).abs(); 12479df49d7eSJed Brown assert!( 12484b61a5a0SRezgar Shakeri error < 50.0 * EPSILON, 12491ce8139fSJeremy L Thompson "Incorrect interval length computed. Expected: 2.0, Found: {}, Error: {:.12e}", 12501ce8139fSJeremy L Thompson sum, 12511ce8139fSJeremy L Thompson error 12529df49d7eSJed Brown ); 125389d15d5fSJeremy L Thompson Ok(()) 12549df49d7eSJed Brown } 12559df49d7eSJed Brown 12569df49d7eSJed Brown #[test] 12579df49d7eSJed Brown fn test_ceed_t501() { 12589df49d7eSJed Brown assert!(ceed_t501().is_ok()); 12599df49d7eSJed Brown } 12609df49d7eSJed Brown } 12619df49d7eSJed Brown 12629df49d7eSJed Brown // ----------------------------------------------------------------------------- 1263